Initial contents for R3_3_2_pathces from R3_3_maintenance
diff --git a/bundles/org.eclipse.wst.sse.core/.classpath b/bundles/org.eclipse.wst.sse.core/.classpath
new file mode 100644
index 0000000..df9dea9
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/.classpath
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src-encoding"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="src-tasktags"/>
+	<classpathentry kind="src" path="src-contentproperties"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4">
+		<accessrules>
+			<accessrule kind="accessible" pattern="org/w3c/dom/traversal/NodeIterator"/>
+		</accessrules>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.wst.sse.core/.cvsignore b/bundles/org.eclipse.wst.sse.core/.cvsignore
new file mode 100644
index 0000000..a71230f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/.cvsignore
@@ -0,0 +1,9 @@
+bin
+model.jar
+build.xml
+temp.folder
+org.eclipse.wst.sse.core_1.0.0.jar
+@dot
+src.zip
+.fbwarnings
+javaCompiler...args
diff --git a/bundles/org.eclipse.wst.sse.core/.options b/bundles/org.eclipse.wst.sse.core/.options
new file mode 100644
index 0000000..50b0b16
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/.options
@@ -0,0 +1,19 @@
+org.eclipse.wst.sse.core/debug=true
+org.eclipse.wst.sse.core/dom/adapter/notification/time=false
+org.eclipse.wst.sse.core/dom/adapter/notification/time/criteria=10
+org.eclipse.wst.sse.core/structureddocument=false
+org.eclipse.wst.sse.core/filebuffers/modelmanagement=false
+org.eclipse.wst.sse.core/filebuffers/leaks=true
+org.eclipse.wst.sse.core/filebuffers/lifecycle=false
+org.eclipse.wst.sse.core/structuredmodel/lifecycle=false
+org.eclipse.wst.sse.core/structuredmodel/state=false
+org.eclipse.wst.sse.core/structuredmodel/locks=true
+org.eclipse.wst.sse.core/structuredmodel/modelmanager=false
+org.eclipse.wst.sse.core/tasks=false
+org.eclipse.wst.sse.core/tasks/detection=false
+org.eclipse.wst.sse.core/tasks/job=false
+org.eclipse.wst.sse.core/tasks/overalltime=false
+org.eclipse.wst.sse.core/tasks/time=false
+org.eclipse.wst.sse.core/tasks/preferences=false
+org.eclipse.wst.sse.core/tasks/registry=false
+org.eclipse.wst.sse.core/format=false
diff --git a/bundles/org.eclipse.wst.sse.core/.project b/bundles/org.eclipse.wst.sse.core/.project
new file mode 100644
index 0000000..36c5b34
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.wst.sse.core</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.core.resources.prefs b/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..afa5c91
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+encoding/<project>=ISO-8859-1
diff --git a/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..7ec5750
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Apr 17 01:48:39 EDT 2006
+eclipse.preferences.version=1
+line.separator=\r\n
diff --git a/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..104e60d
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,80 @@
+#Sat Mar 24 11:23:54 EDT 2007

+eclipse.preferences.version=1

+org.eclipse.jdt.core.builder.cleanOutputFolder=clean

+org.eclipse.jdt.core.builder.duplicateResourceTask=warning

+org.eclipse.jdt.core.builder.invalidClasspath=ignore

+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch

+org.eclipse.jdt.core.circularClasspath=error

+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled

+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled

+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled

+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2

+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve

+org.eclipse.jdt.core.compiler.compliance=1.4

+org.eclipse.jdt.core.compiler.debug.lineNumber=generate

+org.eclipse.jdt.core.compiler.debug.localVariable=generate

+org.eclipse.jdt.core.compiler.debug.sourceFile=generate

+org.eclipse.jdt.core.compiler.doc.comment.support=enabled

+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100

+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning

+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning

+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore

+org.eclipse.jdt.core.compiler.problem.deprecation=ignore

+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled

+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled

+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning

+org.eclipse.jdt.core.compiler.problem.emptyStatement=error

+org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning

+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning

+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore

+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore

+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error

+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error

+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning

+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning

+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore

+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error

+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled

+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private

+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore

+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error

+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public

+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled

+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private

+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore

+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=error

+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error

+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning

+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore

+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning

+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error

+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=enabled

+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error

+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled

+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore

+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=ignore

+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning

+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore

+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning

+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore

+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error

+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore

+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled

+org.eclipse.jdt.core.compiler.problem.unusedImport=error

+org.eclipse.jdt.core.compiler.problem.unusedLabel=error

+org.eclipse.jdt.core.compiler.problem.unusedLocal=error

+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled

+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled

+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error

+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning

+org.eclipse.jdt.core.compiler.source=1.3

+org.eclipse.jdt.core.incompatibleJDKLevel=ignore

+org.eclipse.jdt.core.incompleteClasspath=error

diff --git a/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..301c7ad
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,4 @@
+#Mon Apr 17 01:48:39 EDT 2006
+eclipse.preferences.version=1
+internal.default.compliance=default
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?>\r\n<templates/>
diff --git a/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.ltk.core.refactoring.prefs b/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..c59368c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Tue Apr 04 03:36:32 EDT 2006
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..fc522bb
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,16 @@
+#Mon Apr 17 02:01:33 EDT 2006
+compilers.incompatible-environment=0
+compilers.p.build=0
+compilers.p.deprecated=1
+compilers.p.illegal-att-value=0
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=0
+compilers.p.unknown-attribute=0
+compilers.p.unknown-class=0
+compilers.p.unknown-element=0
+compilers.p.unknown-resource=0
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.p.unused-element-or-attribute=0
+compilers.use-project=true
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/CSSHeadTokenizer.jFlex b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/CSSHeadTokenizer.jFlex
new file mode 100644
index 0000000..bd7272a
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/CSSHeadTokenizer.jFlex
@@ -0,0 +1,279 @@
+/*******************************************************************************

+ * Copyright (c) 2004, 2008 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

+ *******************************************************************************/

+/*nlsXXX*/

+package org.eclipse.wst.css.core.internal.contenttype;

+import java.io.IOException;

+import java.io.Reader;

+

+import org.eclipse.wst.xml.core.internal.contenttype.EncodingParserConstants;

+import org.eclipse.wst.xml.core.internal.contenttype.XMLHeadTokenizerConstants;

+

+

+

+%%

+

+%{

+

+

+	private boolean hasMore = true;

+	private final static int MAX_TO_SCAN = 8000;

+	StringBuffer string = new StringBuffer();

+	// state stack for easier state handling

+	private IntStack fStateStack = new IntStack();

+	private String valueText = null;

+

+

+

+	public CSSHeadTokenizer() {

+		super();

+	}

+

+	  public void reset (Reader in) {

+	  	/* the input device */

+	  	yy_reader = in;

+

+  		/* the current state of the DFA */

+  		yy_state = 0;

+

+  		/* the current lexical state */

+  		yy_lexical_state = YYINITIAL;

+

+  		/* this buffer contains the current text to be matched and is

+  		 the source of the yytext() string */

+  		java.util.Arrays.fill(yy_buffer, (char)0);

+

+  		/* the textposition at the last accepting state */

+  		yy_markedPos = 0;

+

+  		/* the textposition at the last state to be included in yytext */

+  		yy_pushbackPos = 0;

+

+  		/* the current text position in the buffer */

+  		yy_currentPos = 0;

+

+  		/* startRead marks the beginning of the yytext() string in the buffer */

+  		yy_startRead = 0;

+

+  		/** 

+  		 * endRead marks the last character in the buffer, that has been read

+  		 * from input 

+  		 */

+  		yy_endRead = 0;

+

+  		/* number of newlines encountered up to the start of the matched text */

+  		yyline = 0;

+

+  		/* the number of characters up to the start of the matched text */

+  		yychar = 0;

+

+  		/**

+  		 * the number of characters from the last newline up to the start

+  		 * of the matched text

+  		 */

+  		yycolumn = 0; 

+

+  		/** 

+  		 * yy_atBOL == true <=> the scanner is currently at the beginning 

+  		 * of a line

+  		 */

+  		yy_atBOL = false;

+

+  		/* yy_atEOF == true <=> the scanner has returned a value for EOF */

+  		yy_atEOF = false;

+

+  		/* denotes if the user-EOF-code has already been executed */

+  		yy_eof_done = false;

+

+

+  		fStateStack.clear();

+  		

+  		hasMore = true;

+  		

+		// its a little wasteful to "throw away" first char array generated

+		// by class init (via auto generated code), but we really do want

+		// a small buffer for our head parsers.

+		if (yy_buffer.length != MAX_TO_SCAN) {

+			yy_buffer = new char[MAX_TO_SCAN];

+		}

+  		

+

+  	}

+

+

+	public final HeadParserToken getNextToken() throws IOException {

+		String context = null;

+		context = primGetNextToken();

+		HeadParserToken result = null;

+		if (valueText != null) {

+			result = createToken(context, yychar, valueText);

+			valueText = null;

+		} else {

+			result = createToken(context, yychar, yytext());

+		}

+		return result;

+	}

+

+	public final boolean hasMoreTokens() {

+		return hasMore && yychar < MAX_TO_SCAN;

+	}

+	private void pushCurrentState() {

+		fStateStack.push(yystate());

+

+	}

+

+	private void popState() {

+		yybegin(fStateStack.pop());

+	}

+	private HeadParserToken createToken(String context, int start, String text) {

+		return new HeadParserToken(context, start, text);

+	}

+	

+

+%}

+

+%eof{

+	hasMore=false;

+%eof}

+

+%public

+%class CSSHeadTokenizer

+%function primGetNextToken

+%type String

+%char

+%unicode

+%ignorecase 

+%debug

+%switch

+

+

+UTF16BE = \xFE\xFF

+UTF16LE = \xFF\xFE

+UTF83ByteBOM = \xEF\xBB\xBF

+

+//SpaceChar = [\x20\x09]

+

+

+

+// [3] S ::= (0x20 | 0x9 | 0xD | 0xA)+

+S = [\x20\x09\x0D\x0A]

+

+//BeginAttribeValue = {S}* \= {S}*

+

+LineTerminator = \r|\n

+

+// Z is the single-byte zero character to be used in parsing double-byte files

+Z = (\x00)?

+S_UTF = {Z}{S}{Z}

+BeginAttributeValueUTF = {S_UTF}* \= {S_UTF}*

+

+%state ST_XMLDecl

+%state CHARSET_RULE

+%state QuotedAttributeValue

+%state DQ_STRING

+%state SQ_STRING

+%state UnDelimitedString

+

+%%

+

+

+<YYINITIAL>  

+{

+	{UTF16BE}   		{hasMore = false; return EncodingParserConstants.UTF16BE;}

+	{UTF16LE}   		{hasMore = false; return EncodingParserConstants.UTF16LE;}

+	{UTF83ByteBOM}   	{hasMore = false; return EncodingParserConstants.UTF83ByteBOM;}

+

+	// force to be started on first line, but we do allow preceeding spaces

+	^ {Z}({S}{Z})* ({Z}<{Z}\?{Z}x{Z}m{Z}l{Z}){S_UTF}+ {if (yychar == 0 ) {yybegin(ST_XMLDecl); return XMLHeadTokenizerConstants.XMLDeclStart;}}

+	

+	^ {Z}({S}{Z})*({Z}@{Z}c{Z}h{Z}a{Z}r{Z}s{Z}e{Z}t{Z})   {if (yychar == 0 )  {yybegin(CHARSET_RULE); return CSSHeadTokenizerConstants.CHARSET_RULE;}}

+}	

+

+// I don't think there's really an XML form of CSS files ... but will leave here for consistency	

+<ST_XMLDecl> 

+{

+	//"version" {BeginAttribeValue} {pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDeclVersion;}

+	{Z}e{Z}n{Z}c{Z}o{Z}d{Z}i{Z}n{Z}g{Z} {BeginAttributeValueUTF} {pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDelEncoding;}

+	// note this "forced end" once end of XML Declaration found

+	{Z}\?{Z}>{Z}    {yybegin(YYINITIAL);  return XMLHeadTokenizerConstants.XMLDeclEnd;}

+}	

+

+<CHARSET_RULE> 

+{

+

+	{S_UTF}*  {pushCurrentState(); yybegin(QuotedAttributeValue);}

+	{Z};{Z}    { yybegin(YYINITIAL);  hasMore = false; return CSSHeadTokenizerConstants.RuleEnd;}

+}

+	

+

+<QuotedAttributeValue>

+{

+	{Z}\"{Z}                     { yybegin(DQ_STRING); string.setLength(0); }

+	{Z}\'{Z}			{ yybegin(SQ_STRING); string.setLength(0); }

+	// in this state, anything other than a space character can start an undelimited string

+	{S_UTF}*.           { yypushback(yylength()); yybegin(UnDelimitedString); string.setLength(0);}

+

+}	

+

+

+<DQ_STRING>

+{

+

+	{Z}\"{Z}                      { popState(); valueText = string.toString(); return EncodingParserConstants.StringValue; }

+  	{Z}{LineTerminator}{Z}        { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}\?{Z}>{Z}			{ yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}<{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	

+	{Z}>{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}\/{Z}>{Z}			{ yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z};{Z}                      { yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue; }

+	[^\x00]			{ string.append( yytext() ); }

+

+

+}

+

+<SQ_STRING>

+{

+

+	{Z}\'{Z}                      { popState(); valueText = string.toString(); return EncodingParserConstants.StringValue;}

+  	{Z}{LineTerminator}{Z}        { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}%{Z}>{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}<{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}>{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}\/{Z}>{Z}			{ yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z};{Z}                      { yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue; }

+	[^\x00]			{ string.append( yytext() ); }

+

+}

+

+<UnDelimitedString>

+{

+

+

+	{S_UTF}                     { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.UnDelimitedStringValue; }

+  	{Z}{LineTerminator}{Z}        { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}\?{Z}>{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}<{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	// these are a bit special, since we started an undelimit string, but found a quote ... probably indicates a missing beginning quote

+	{Z}\'{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;}

+	{Z}\"{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;}

+	

+	{Z}>{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}\/{Z}>{Z}			{ yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z};{Z}                      { yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.UnDelimitedStringValue; }

+	[^\x00]			{ string.append( yytext() ); }

+}

+

+// The "match anything" rule should always be in effect except for when looking for end of string

+// (That is, remember to update state list if/when new states added)

+.|\n	{if(yychar > MAX_TO_SCAN) {hasMore=false; return EncodingParserConstants.MAX_CHARS_REACHED;}}

+

+// this rule always in effect

+<<EOF>>         {hasMore = false; return EncodingParserConstants.EOF;}

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/CSSHeadTokenizer.java b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/CSSHeadTokenizer.java
new file mode 100644
index 0000000..d2309dd
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/CSSHeadTokenizer.java
@@ -0,0 +1,1441 @@
+/* The following code was generated by JFlex 1.2.2 on 7/28/08 5:19 PM */
+
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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
+ *******************************************************************************/
+/*nlsXXX*/
+package org.eclipse.wst.css.core.internal.contenttype;
+import java.io.IOException;
+import java.io.Reader;
+
+import org.eclipse.wst.xml.core.internal.contenttype.EncodingParserConstants;
+import org.eclipse.wst.xml.core.internal.contenttype.XMLHeadTokenizerConstants;
+
+
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.informatik.tu-muenchen.de/~kleing/jflex/">JFlex</a> 1.2.2
+ * on 7/28/08 5:19 PM from the specification file
+ * <tt>file:/D:/workspaces/wtp301/workspace/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/CSSHeadTokenizer.jFlex</tt>
+ */
+public class CSSHeadTokenizer {
+
+  /** this character denotes the end of file */
+  final public static int YYEOF = -1;
+
+  /** lexical states */
+  final public static int YYINITIAL = 0;
+  final public static int UnDelimitedString = 12;
+  final public static int DQ_STRING = 8;
+  final public static int SQ_STRING = 10;
+  final public static int ST_XMLDecl = 2;
+  final public static int QuotedAttributeValue = 6;
+  final public static int CHARSET_RULE = 4;
+
+  /**
+   * YY_LEXSTATE[l] is the state in the DFA for the lexical state l
+   * YY_LEXSTATE[l+1] is the state in the DFA for the lexical state l
+   *                  at the beginning of a line
+   * l is of the form l = 2*k, k a non negative integer
+   */
+  private final static int YY_LEXSTATE[] = { 
+     0,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,  7, 7
+  };
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static String yycmap_packed = 
+    "\1\11\10\0\1\6\1\10\2\0\1\7\22\0\1\6\1\0\1\37"+
+    "\2\0\1\42\1\0\1\40\7\0\1\41\13\0\1\36\1\13\1\12"+
+    "\1\35\1\14\1\20\1\23\1\0\1\21\1\32\1\26\1\0\1\34"+
+    "\1\22\1\33\2\0\1\17\1\16\1\30\1\31\2\0\1\24\1\25"+
+    "\1\27\3\0\1\15\10\0\1\23\1\0\1\21\1\32\1\26\1\0"+
+    "\1\34\1\22\1\33\2\0\1\17\1\16\1\30\1\31\2\0\1\24"+
+    "\1\25\1\27\3\0\1\15\102\0\1\4\3\0\1\5\17\0\1\3"+
+    "\16\0\1\1\20\0\1\3\16\0\1\1\1\2\170\0\1\2\ufe87\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static char [] yycmap = yy_unpack_cmap(yycmap_packed);
+
+
+  /* error codes */
+  final private static int YY_UNKNOWN_ERROR = 0;
+  final private static int YY_ILLEGAL_STATE = 1;
+  final private static int YY_NO_MATCH = 2;
+  final private static int YY_PUSHBACK_2BIG = 3;
+
+  /* error messages for the codes above */
+  final private static String YY_ERROR_MSG[] = {
+    "Unkown internal scanner error",
+    "Internal error: unknown state",
+    "Error: could not match input",
+    "Error: pushback value was too large"
+  };
+
+  /** the input device */
+  private java.io.Reader yy_reader;
+
+  /** the current state of the DFA */
+  private int yy_state;
+
+  /** the current lexical state */
+  private int yy_lexical_state = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private char yy_buffer[] = new char[16384];
+
+  /** the textposition at the last accepting state */
+  private int yy_markedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int yy_pushbackPos;
+
+  /** the current text position in the buffer */
+  private int yy_currentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int yy_startRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int yy_endRead;
+
+  /** number of newlines encountered up to the start of the matched text */
+  private int yyline;
+
+  /** the number of characters up to the start of the matched text */
+  private int yychar;
+
+  /**
+   * the number of characters from the last newline up to the start of the 
+   * matched text
+   */
+  private int yycolumn; 
+
+  /** 
+   * yy_atBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  private boolean yy_atBOL;
+
+  /** yy_atEOF == true <=> the scanner has returned a value for EOF */
+  private boolean yy_atEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean yy_eof_done;
+
+  /* user code: */
+
+
+	private boolean hasMore = true;
+	private final static int MAX_TO_SCAN = 8000;
+	StringBuffer string = new StringBuffer();
+	// state stack for easier state handling
+	private IntStack fStateStack = new IntStack();
+	private String valueText = null;
+
+
+
+	public CSSHeadTokenizer() {
+		super();
+	}
+
+	  public void reset (Reader in) {
+	  	/* the input device */
+	  	yy_reader = in;
+
+  		/* the current state of the DFA */
+  		yy_state = 0;
+
+  		/* the current lexical state */
+  		yy_lexical_state = YYINITIAL;
+
+  		/* this buffer contains the current text to be matched and is
+  		 the source of the yytext() string */
+  		java.util.Arrays.fill(yy_buffer, (char)0);
+
+  		/* the textposition at the last accepting state */
+  		yy_markedPos = 0;
+
+  		/* the textposition at the last state to be included in yytext */
+  		yy_pushbackPos = 0;
+
+  		/* the current text position in the buffer */
+  		yy_currentPos = 0;
+
+  		/* startRead marks the beginning of the yytext() string in the buffer */
+  		yy_startRead = 0;
+
+  		/** 
+  		 * endRead marks the last character in the buffer, that has been read
+  		 * from input 
+  		 */
+  		yy_endRead = 0;
+
+  		/* number of newlines encountered up to the start of the matched text */
+  		yyline = 0;
+
+  		/* the number of characters up to the start of the matched text */
+  		yychar = 0;
+
+  		/**
+  		 * the number of characters from the last newline up to the start
+  		 * of the matched text
+  		 */
+  		yycolumn = 0; 
+
+  		/** 
+  		 * yy_atBOL == true <=> the scanner is currently at the beginning 
+  		 * of a line
+  		 */
+  		yy_atBOL = false;
+
+  		/* yy_atEOF == true <=> the scanner has returned a value for EOF */
+  		yy_atEOF = false;
+
+  		/* denotes if the user-EOF-code has already been executed */
+  		yy_eof_done = false;
+
+
+  		fStateStack.clear();
+  		
+  		hasMore = true;
+  		
+		// its a little wasteful to "throw away" first char array generated
+		// by class init (via auto generated code), but we really do want
+		// a small buffer for our head parsers.
+		if (yy_buffer.length != MAX_TO_SCAN) {
+			yy_buffer = new char[MAX_TO_SCAN];
+		}
+  		
+
+  	}
+
+
+	public final HeadParserToken getNextToken() throws IOException {
+		String context = null;
+		context = primGetNextToken();
+		HeadParserToken result = null;
+		if (valueText != null) {
+			result = createToken(context, yychar, valueText);
+			valueText = null;
+		} else {
+			result = createToken(context, yychar, yytext());
+		}
+		return result;
+	}
+
+	public final boolean hasMoreTokens() {
+		return hasMore && yychar < MAX_TO_SCAN;
+	}
+	private void pushCurrentState() {
+		fStateStack.push(yystate());
+
+	}
+
+	private void popState() {
+		yybegin(fStateStack.pop());
+	}
+	private HeadParserToken createToken(String context, int start, String text) {
+		return new HeadParserToken(context, start, text);
+	}
+	
+
+
+
+  /**
+   * Creates a new scanner
+   * There is also a java.io.InputStream version of this constructor.
+   *
+   * @param   in  the java.io.Reader to read input from.
+   */
+  public CSSHeadTokenizer(java.io.Reader in) {
+    this.yy_reader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  public CSSHeadTokenizer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] yy_unpack_cmap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 160) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+
+  /**
+   * Gets the next input character.
+   *
+   * @return      the next character of the input stream, EOF if the
+   *              end of the stream is reached.
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  private int yy_advance() throws java.io.IOException {
+
+    /* standard case */
+    if (yy_currentPos < yy_endRead) return yy_buffer[yy_currentPos++];
+
+    /* if the eof is reached, we don't need to work hard */ 
+    if (yy_atEOF) return YYEOF;
+
+    /* otherwise: need to refill the buffer */
+
+    /* first: make room (if you can) */
+    if (yy_startRead > 0) {
+      System.arraycopy(yy_buffer, yy_startRead, 
+                       yy_buffer, 0, 
+                       yy_endRead-yy_startRead);
+
+      /* translate stored positions */
+      yy_endRead-= yy_startRead;
+      yy_currentPos-= yy_startRead;
+      yy_markedPos-= yy_startRead;
+      yy_pushbackPos-= yy_startRead;
+      yy_startRead = 0;
+    }
+
+    /* is the buffer big enough? */
+    if (yy_currentPos >= yy_buffer.length) {
+      /* if not: blow it up */
+      char newBuffer[] = new char[yy_currentPos*2];
+      System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);
+      yy_buffer = newBuffer;
+    }
+
+    /* finally: fill the buffer with new input */
+    int numRead = yy_reader.read(yy_buffer, yy_endRead, 
+                                            yy_buffer.length-yy_endRead);
+
+    if ( numRead == -1 ) return YYEOF;
+
+    yy_endRead+= numRead;
+
+    return yy_buffer[yy_currentPos++];
+  }
+
+
+  /**
+   * Closes the input stream.
+   */
+  final public void yyclose() throws java.io.IOException {
+    yy_atEOF = true;            /* indicate end of file */
+    yy_endRead = yy_startRead;  /* invalidate buffer    */
+    yy_reader.close();
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  final public int yystate() {
+    return yy_lexical_state;
+  }
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  final public void yybegin(int newState) {
+    yy_lexical_state = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  final public String yytext() {
+    return new String( yy_buffer, yy_startRead, yy_markedPos-yy_startRead );
+  }
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  final public int yylength() {
+    return yy_markedPos-yy_startRead;
+  }
+
+
+  /**
+   * Reports an error that occured while scanning.
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void yy_ScanError(int errorCode) {
+    try {
+      System.out.println(YY_ERROR_MSG[errorCode]);
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      System.out.println(YY_ERROR_MSG[YY_UNKNOWN_ERROR]);
+    }
+
+    System.exit(1);
+  } 
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+  private void yypushback(int number) {
+    if ( number > yylength() )
+      yy_ScanError(YY_PUSHBACK_2BIG);
+
+    yy_markedPos -= number;
+  }
+
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void yy_do_eof() {
+    if (!yy_eof_done) {
+      yy_eof_done = true;
+    	hasMore=false;
+
+    }
+  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  public String primGetNextToken() throws java.io.IOException {
+    int yy_input;
+    int yy_action;
+
+
+    while (true) {
+
+      yychar+= yylength();
+
+      yy_atBOL = yy_markedPos <= 0 || yy_buffer[yy_markedPos-1] == '\n';
+      if (!yy_atBOL && yy_buffer[yy_markedPos-1] == '\r') {
+        yy_atBOL = yy_advance() != '\n';
+        if (!yy_atEOF) yy_currentPos--;
+      }
+
+      yy_action = -1;
+
+      yy_currentPos = yy_startRead = yy_markedPos;
+
+      if (yy_atBOL)
+        yy_state = YY_LEXSTATE[yy_lexical_state+1];
+      else
+        yy_state = YY_LEXSTATE[yy_lexical_state];
+
+
+      yy_forAction: {
+        while (true) {
+
+          yy_input = yy_advance();
+
+          if ( yy_input == YYEOF ) break yy_forAction;
+
+          yy_input = yycmap[yy_input];
+
+          boolean yy_isFinal = false;
+          boolean yy_noLookAhead = false;
+
+          yy_forNext: { switch (yy_state) {
+            case 0:
+              switch (yy_input) {
+                case 1: yy_isFinal = true; yy_state = 9; break yy_forNext;
+                case 2: yy_isFinal = true; yy_state = 10; break yy_forNext;
+                case 3: yy_isFinal = true; yy_state = 11; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 8; break yy_forNext;
+              }
+
+            case 1:
+              switch (yy_input) {
+                case 1: yy_isFinal = true; yy_state = 9; break yy_forNext;
+                case 2: yy_isFinal = true; yy_state = 10; break yy_forNext;
+                case 3: yy_isFinal = true; yy_state = 11; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 12; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 13; break yy_forNext;
+                case 11: yy_isFinal = true; yy_state = 14; break yy_forNext;
+                case 16: yy_isFinal = true; yy_state = 15; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 8; break yy_forNext;
+              }
+
+            case 2:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_state = 16; break yy_forNext;
+                case 12: yy_isFinal = true; yy_state = 17; break yy_forNext;
+                case 22: yy_isFinal = true; yy_state = 18; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 8; break yy_forNext;
+              }
+
+            case 3:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 19; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 20; break yy_forNext;
+                case 30: yy_isFinal = true; yy_state = 21; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 8; break yy_forNext;
+              }
+
+            case 4:
+              switch (yy_input) {
+                case 6: 
+                case 7: yy_isFinal = true; yy_state = 23; break yy_forNext;
+                case 8: yy_isFinal = true; yy_state = 24; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 25; break yy_forNext;
+                case 31: yy_isFinal = true; yy_state = 26; break yy_forNext;
+                case 32: yy_isFinal = true; yy_state = 27; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 22; break yy_forNext;
+              }
+
+            case 5:
+              switch (yy_input) {
+                case 7: 
+                case 8: 
+                case 11: 
+                case 29: yy_isFinal = true; yy_state = 29; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 30; break yy_forNext;
+                case 12: 
+                case 33: yy_isFinal = true; yy_state = 31; break yy_forNext;
+                case 30: yy_isFinal = true; yy_state = 32; break yy_forNext;
+                case 31: yy_isFinal = true; yy_state = 33; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 28; break yy_forNext;
+              }
+
+            case 6:
+              switch (yy_input) {
+                case 7: 
+                case 8: 
+                case 11: 
+                case 29: yy_isFinal = true; yy_state = 29; break yy_forNext;
+                case 33: yy_isFinal = true; yy_state = 31; break yy_forNext;
+                case 30: yy_isFinal = true; yy_state = 32; break yy_forNext;
+                case 32: yy_isFinal = true; yy_state = 33; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 34; break yy_forNext;
+                case 34: yy_isFinal = true; yy_state = 35; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 28; break yy_forNext;
+              }
+
+            case 7:
+              switch (yy_input) {
+                case 11: 
+                case 29: yy_isFinal = true; yy_state = 29; break yy_forNext;
+                case 33: yy_isFinal = true; yy_state = 31; break yy_forNext;
+                case 12: yy_isFinal = true; yy_state = 35; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 36; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 37; break yy_forNext;
+                case 30: yy_isFinal = true; yy_state = 38; break yy_forNext;
+                case 31: 
+                case 32: yy_isFinal = true; yy_state = 39; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 28; break yy_forNext;
+              }
+
+            case 9:
+              switch (yy_input) {
+                case 2: yy_isFinal = true; yy_noLookAhead = true; yy_state = 40; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 10:
+              switch (yy_input) {
+                case 1: yy_isFinal = true; yy_noLookAhead = true; yy_state = 41; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 11:
+              switch (yy_input) {
+                case 4: yy_state = 42; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 12:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 43; break yy_forNext;
+                case 9: yy_state = 44; break yy_forNext;
+                case 11: yy_state = 45; break yy_forNext;
+                case 16: yy_state = 46; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 13:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 43; break yy_forNext;
+                case 11: yy_state = 45; break yy_forNext;
+                case 16: yy_state = 46; break yy_forNext;
+                case 9: yy_state = 47; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 14:
+              switch (yy_input) {
+                case 9: yy_state = 48; break yy_forNext;
+                case 12: yy_state = 49; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 15:
+              switch (yy_input) {
+                case 9: yy_state = 50; break yy_forNext;
+                case 17: yy_state = 51; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 16:
+              switch (yy_input) {
+                case 12: yy_state = 52; break yy_forNext;
+                case 22: yy_state = 53; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 17:
+              switch (yy_input) {
+                case 9: yy_state = 54; break yy_forNext;
+                case 29: yy_isFinal = true; yy_state = 55; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 18:
+              switch (yy_input) {
+                case 9: yy_state = 56; break yy_forNext;
+                case 24: yy_state = 57; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 19:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 19; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 58; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 20:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 19; break yy_forNext;
+                case 30: yy_isFinal = true; yy_state = 21; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 21:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 59; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 23:
+              switch (yy_input) {
+                case 6: 
+                case 7: yy_isFinal = true; yy_state = 23; break yy_forNext;
+                case 8: yy_state = 60; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 61; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 22; break yy_forNext;
+              }
+
+            case 24:
+              switch (yy_input) {
+                case 6: 
+                case 7: yy_isFinal = true; yy_state = 23; break yy_forNext;
+                case 8: yy_state = 60; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 61; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 22; break yy_forNext;
+              }
+
+            case 25:
+              switch (yy_input) {
+                case 31: yy_isFinal = true; yy_state = 26; break yy_forNext;
+                case 32: yy_isFinal = true; yy_state = 27; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_state = 60; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 26:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 62; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 27:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 63; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 29:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 64; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 30:
+              switch (yy_input) {
+                case 7: 
+                case 8: 
+                case 11: 
+                case 29: yy_isFinal = true; yy_state = 29; break yy_forNext;
+                case 30: yy_isFinal = true; yy_state = 32; break yy_forNext;
+                case 31: yy_isFinal = true; yy_state = 33; break yy_forNext;
+                case 12: 
+                case 33: yy_state = 65; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 31:
+              switch (yy_input) {
+                case 29: yy_isFinal = true; yy_state = 32; break yy_forNext;
+                case 9: yy_state = 66; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 32:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 67; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 33:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 68; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 34:
+              switch (yy_input) {
+                case 7: 
+                case 8: 
+                case 11: 
+                case 29: yy_isFinal = true; yy_state = 29; break yy_forNext;
+                case 30: yy_isFinal = true; yy_state = 32; break yy_forNext;
+                case 32: yy_isFinal = true; yy_state = 33; break yy_forNext;
+                case 33: yy_state = 65; break yy_forNext;
+                case 34: yy_state = 69; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 35:
+              switch (yy_input) {
+                case 29: yy_isFinal = true; yy_state = 29; break yy_forNext;
+                case 9: yy_state = 70; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 36:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 71; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 37:
+              switch (yy_input) {
+                case 11: 
+                case 29: yy_isFinal = true; yy_state = 29; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 36; break yy_forNext;
+                case 30: yy_isFinal = true; yy_state = 38; break yy_forNext;
+                case 31: 
+                case 32: yy_isFinal = true; yy_state = 39; break yy_forNext;
+                case 33: yy_state = 65; break yy_forNext;
+                case 12: yy_state = 69; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 38:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 72; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 39:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 73; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 42:
+              switch (yy_input) {
+                case 5: yy_isFinal = true; yy_noLookAhead = true; yy_state = 74; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 43:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 43; break yy_forNext;
+                case 9: yy_state = 44; break yy_forNext;
+                case 11: yy_state = 45; break yy_forNext;
+                case 16: yy_state = 46; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 44:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 43; break yy_forNext;
+                case 11: yy_state = 45; break yy_forNext;
+                case 16: yy_state = 46; break yy_forNext;
+                case 9: yy_state = 47; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 45:
+              switch (yy_input) {
+                case 9: yy_state = 48; break yy_forNext;
+                case 12: yy_state = 49; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 46:
+              switch (yy_input) {
+                case 9: yy_state = 50; break yy_forNext;
+                case 17: yy_state = 51; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 47:
+              switch (yy_input) {
+                case 11: yy_state = 45; break yy_forNext;
+                case 16: yy_state = 46; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 48:
+              switch (yy_input) {
+                case 12: yy_state = 49; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 49:
+              switch (yy_input) {
+                case 9: yy_state = 75; break yy_forNext;
+                case 13: yy_state = 76; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 50:
+              switch (yy_input) {
+                case 17: yy_state = 51; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 51:
+              switch (yy_input) {
+                case 9: yy_state = 77; break yy_forNext;
+                case 18: yy_state = 78; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 52:
+              switch (yy_input) {
+                case 9: yy_state = 54; break yy_forNext;
+                case 29: yy_isFinal = true; yy_state = 55; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 53:
+              switch (yy_input) {
+                case 9: yy_state = 56; break yy_forNext;
+                case 24: yy_state = 57; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 54:
+              switch (yy_input) {
+                case 29: yy_isFinal = true; yy_state = 55; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 55:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 79; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 56:
+              switch (yy_input) {
+                case 24: yy_state = 57; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 57:
+              switch (yy_input) {
+                case 9: yy_state = 80; break yy_forNext;
+                case 17: yy_state = 81; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 58:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 19; break yy_forNext;
+                case 9: yy_state = 82; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 60:
+              switch (yy_input) {
+                case 6: 
+                case 7: yy_isFinal = true; yy_state = 23; break yy_forNext;
+                case 8: yy_state = 60; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 61; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 22; break yy_forNext;
+              }
+
+            case 61:
+              switch (yy_input) {
+                case 6: 
+                case 7: yy_isFinal = true; yy_state = 23; break yy_forNext;
+                case 8: yy_state = 60; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 83; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 22; break yy_forNext;
+              }
+
+            case 65:
+              switch (yy_input) {
+                case 29: yy_isFinal = true; yy_state = 32; break yy_forNext;
+                case 9: yy_state = 66; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 66:
+              switch (yy_input) {
+                case 29: yy_isFinal = true; yy_state = 32; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 69:
+              switch (yy_input) {
+                case 29: yy_isFinal = true; yy_state = 29; break yy_forNext;
+                case 9: yy_state = 70; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 70:
+              switch (yy_input) {
+                case 29: yy_isFinal = true; yy_state = 29; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 75:
+              switch (yy_input) {
+                case 13: yy_state = 76; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 76:
+              switch (yy_input) {
+                case 9: yy_state = 84; break yy_forNext;
+                case 14: yy_state = 85; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 77:
+              switch (yy_input) {
+                case 18: yy_state = 78; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 78:
+              switch (yy_input) {
+                case 9: yy_state = 86; break yy_forNext;
+                case 19: yy_state = 87; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 80:
+              switch (yy_input) {
+                case 17: yy_state = 81; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 81:
+              switch (yy_input) {
+                case 9: yy_state = 88; break yy_forNext;
+                case 25: yy_state = 89; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 82:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 19; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 83:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 60; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 84:
+              switch (yy_input) {
+                case 14: yy_state = 85; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 85:
+              switch (yy_input) {
+                case 9: yy_state = 90; break yy_forNext;
+                case 15: yy_state = 91; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 86:
+              switch (yy_input) {
+                case 19: yy_state = 87; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 87:
+              switch (yy_input) {
+                case 9: yy_state = 92; break yy_forNext;
+                case 20: yy_state = 93; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 88:
+              switch (yy_input) {
+                case 25: yy_state = 89; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 89:
+              switch (yy_input) {
+                case 9: yy_state = 94; break yy_forNext;
+                case 26: yy_state = 95; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 90:
+              switch (yy_input) {
+                case 15: yy_state = 91; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 91:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 96; break yy_forNext;
+                case 9: yy_state = 97; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 92:
+              switch (yy_input) {
+                case 20: yy_state = 93; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 93:
+              switch (yy_input) {
+                case 9: yy_state = 98; break yy_forNext;
+                case 21: yy_state = 99; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 94:
+              switch (yy_input) {
+                case 26: yy_state = 95; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 95:
+              switch (yy_input) {
+                case 9: yy_state = 100; break yy_forNext;
+                case 27: yy_state = 101; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 96:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 96; break yy_forNext;
+                case 9: yy_isFinal = true; yy_state = 102; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 97:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 96; break yy_forNext;
+                case 9: yy_state = 103; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 98:
+              switch (yy_input) {
+                case 21: yy_state = 99; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 99:
+              switch (yy_input) {
+                case 9: yy_state = 104; break yy_forNext;
+                case 22: yy_state = 105; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 100:
+              switch (yy_input) {
+                case 27: yy_state = 101; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 101:
+              switch (yy_input) {
+                case 9: yy_state = 106; break yy_forNext;
+                case 24: yy_state = 107; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 102:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 96; break yy_forNext;
+                case 9: yy_state = 103; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 103:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 96; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 104:
+              switch (yy_input) {
+                case 22: yy_state = 105; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 105:
+              switch (yy_input) {
+                case 9: yy_state = 108; break yy_forNext;
+                case 23: yy_isFinal = true; yy_state = 109; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 106:
+              switch (yy_input) {
+                case 24: yy_state = 107; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 107:
+              switch (yy_input) {
+                case 9: yy_state = 110; break yy_forNext;
+                case 28: yy_state = 111; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 108:
+              switch (yy_input) {
+                case 23: yy_isFinal = true; yy_state = 109; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 109:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 112; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 110:
+              switch (yy_input) {
+                case 28: yy_state = 111; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 111:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 111; break yy_forNext;
+                case 9: yy_state = 113; break yy_forNext;
+                case 10: yy_isFinal = true; yy_state = 114; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 113:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 111; break yy_forNext;
+                case 10: yy_isFinal = true; yy_state = 114; break yy_forNext;
+                case 9: yy_state = 115; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 114:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 116; break yy_forNext;
+                case 9: yy_state = 117; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 115:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_state = 111; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 116:
+              switch (yy_input) {
+                case 9: yy_isFinal = true; yy_state = 114; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 116; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 117:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 8: yy_isFinal = true; yy_state = 116; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            default:
+              yy_ScanError(YY_ILLEGAL_STATE);
+              break;
+          } }
+
+          if ( yy_isFinal ) {
+            yy_action = yy_state; 
+            yy_markedPos = yy_currentPos; 
+            if ( yy_noLookAhead ) break yy_forAction;
+          }
+
+        }
+      }
+
+
+      switch (yy_action) {    
+
+        case 29: 
+        case 64: 
+          {  yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue; }
+        case 119: break;
+        case 22: 
+        case 23: 
+        case 25: 
+        case 61: 
+        case 83: 
+          {  yypushback(yylength()); yybegin(UnDelimitedString); string.setLength(0); }
+        case 120: break;
+        case 21: 
+        case 59: 
+          {  yybegin(YYINITIAL);  hasMore = false; return CSSHeadTokenizerConstants.RuleEnd; }
+        case 121: break;
+        case 39: 
+        case 73: 
+          {  yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue; }
+        case 122: break;
+        case 109: 
+        case 112: 
+          { if (yychar == 0 )  {yybegin(CHARSET_RULE); return CSSHeadTokenizerConstants.CHARSET_RULE;} }
+        case 123: break;
+        case 96: 
+        case 102: 
+          { if (yychar == 0 ) {yybegin(ST_XMLDecl); return XMLHeadTokenizerConstants.XMLDeclStart;} }
+        case 124: break;
+        case 8: 
+        case 9: 
+        case 10: 
+        case 11: 
+        case 12: 
+        case 13: 
+        case 14: 
+        case 15: 
+        case 16: 
+        case 17: 
+        case 18: 
+        case 20: 
+        case 24: 
+        case 30: 
+        case 34: 
+        case 37: 
+          { if(yychar > MAX_TO_SCAN) {hasMore=false; return EncodingParserConstants.MAX_CHARS_REACHED;} }
+        case 125: break;
+        case 55: 
+        case 79: 
+          { yybegin(YYINITIAL);  return XMLHeadTokenizerConstants.XMLDeclEnd; }
+        case 126: break;
+        case 114: 
+        case 116: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDelEncoding; }
+        case 127: break;
+        case 3: 
+        case 19: 
+        case 58: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); }
+        case 128: break;
+        case 40: 
+          { hasMore = false; return EncodingParserConstants.UTF16BE; }
+        case 129: break;
+        case 41: 
+          { hasMore = false; return EncodingParserConstants.UTF16LE; }
+        case 130: break;
+        case 74: 
+          { hasMore = false; return EncodingParserConstants.UTF83ByteBOM; }
+        case 131: break;
+        case 28: 
+        case 31: 
+        case 35: 
+          {  string.append( yytext() );  }
+        case 132: break;
+        case 27: 
+        case 63: 
+          {  yybegin(SQ_STRING); string.setLength(0);  }
+        case 133: break;
+        case 26: 
+        case 62: 
+          {  yybegin(DQ_STRING); string.setLength(0);  }
+        case 134: break;
+        case 32: 
+        case 67: 
+          {  yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;  }
+        case 135: break;
+        case 33: 
+        case 68: 
+          {  popState(); valueText = string.toString(); return EncodingParserConstants.StringValue;  }
+        case 136: break;
+        case 36: 
+        case 71: 
+          {  yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.UnDelimitedStringValue;  }
+        case 137: break;
+        case 38: 
+        case 72: 
+          {  yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.UnDelimitedStringValue;  }
+        case 138: break;
+        default: 
+          if (yy_input == YYEOF && yy_startRead == yy_currentPos) {
+            yy_atEOF = true;
+            yy_do_eof();
+              { hasMore = false; return EncodingParserConstants.EOF; }
+          } 
+          else {
+            yy_ScanError(YY_NO_MATCH);
+          }
+      }
+    }
+  }    
+
+  /**
+   * Runs the scanner on input files.
+   *
+   * This main method is the debugging routine for the scanner.
+   * It prints each returned token to System.out until the end of
+   * file is reached, or an error occured.
+   *
+   * @param argv   the command line, contains the filenames to run
+   *               the scanner on.
+   */
+  public static void main(String argv[]) {
+    for (int i = 0; i < argv.length; i++) {
+      CSSHeadTokenizer scanner = null;
+      try {
+        scanner = new CSSHeadTokenizer( new java.io.FileReader(argv[i]) );
+      }
+      catch (java.io.FileNotFoundException e) {
+        System.out.println("File not found : \""+argv[i]+"\"");
+        System.exit(1);
+      }
+      catch (java.io.IOException e) {
+        System.out.println("Error opening file \""+argv[i]+"\"");
+        System.exit(1);
+      }
+      catch (ArrayIndexOutOfBoundsException e) {
+        System.out.println("Usage : java CSSHeadTokenizer <inputfile>");
+        System.exit(1);
+      }
+
+      try {
+        do {
+          System.out.println(scanner.primGetNextToken());
+        } while (!scanner.yy_atEOF);
+
+      }
+      catch (java.io.IOException e) {
+        System.out.println("An I/O error occured while scanning :");
+        System.out.println(e);
+        System.exit(1);
+      }
+      catch (Exception e) {
+        e.printStackTrace();
+        System.exit(1);
+      }
+    }
+  }
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/CSSHeadTokenizerGenJava.cmd b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/CSSHeadTokenizerGenJava.cmd
new file mode 100644
index 0000000..9ef06e9
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/CSSHeadTokenizerGenJava.cmd
@@ -0,0 +1,23 @@
+@echo off

+

+rem The following variables need to be set/specified for each "development machine"

+set PATH=%PATH%;d:jdks\j2sdk1.4.1_02\bin

+set WORKSPACE_LOCATION=D:\builds\Workspaces\PureHeadWorkspace

+set JFLEX_LIB_LOCATION=D:\DevTimeSupport\JFlex\lib

+

+rem The following variables differ from project to project, but should be otherwise constant

+set MAIN_NAME=CSSHeadTokenizer

+set PROJECT_SRC=\org.eclipse.wst.common.encoding.contentspecific\src\

+set PACKAGE_DIR=com\ibm\encoding\resource\contentspecific\css\

+

+rem Given the above "framework" and the command themselves, these variables should never need to be modified

+set JAVA_FILE=%MAIN_NAME%.java

+set JFLEX_RULES=%MAIN_NAME%.jflex

+set SKELETON_FILE=%MAIN_NAME%.skeleton

+

+IF EXIST %JAVA_FILE% del %JAVA_FILE%

+rem java -Xmx470000000 -cp %JFLEX_LIB_LOCATION%\sed-jflex.jar;. JFlex.Main %JFLEX_RULES% -skel %SKELETON_FILE% 1>jflexout.txt 2>jflexerr.txt

+java -Xmx470000000 -cp %JFLEX_LIB_LOCATION%\sed-jflex.jar;. JFlex.Main %JFLEX_RULES%  1>jflexout.txt 2>jflexerr.txt

+IF EXIST %JAVA_FILE% copy %JAVA_FILE% %WORKSPACE_LOCATION%%PROJECT_SRC%%PACKAGE_DIR%%JAVA_FILE%

+

+rem pause

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/jflexerr.txt b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/jflexerr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/jflexerr.txt
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/jflexout.txt b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/jflexout.txt
new file mode 100644
index 0000000..e0743ca
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/CSSHeadTokenizer/jflexout.txt
@@ -0,0 +1,6 @@
+Reading "CSSHeadTokenizer.jflex"
+Constructing NFA : 458 states in NFA
+Converting NFA to DFA : 
+........................................................................................
+102 states before minimization, 64 states in minimized DFA
+Writing code to "CSSHeadTokenizer.java"
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/HTMLHeadTokenizer.jFlex b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/HTMLHeadTokenizer.jFlex
new file mode 100644
index 0000000..d35d074
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/HTMLHeadTokenizer.jFlex
@@ -0,0 +1,313 @@
+/*******************************************************************************

+ * Copyright (c) 2004, 2010 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

+ *******************************************************************************/

+/*nlsXXX*/

+package org.eclipse.wst.html.core.internal.contenttype;

+import java.io.IOException;

+import java.io.Reader;

+

+import org.eclipse.wst.xml.core.internal.contenttype.EncodingParserConstants;

+import org.eclipse.wst.xml.core.internal.contenttype.XMLHeadTokenizerConstants;

+

+

+

+%%

+

+%{

+

+

+	private boolean hasMore = true;

+	private boolean hasCharsetAttr = false;

+	private final static int MAX_TO_SCAN = 8000;

+	StringBuffer string = new StringBuffer();

+	// state stack for easier state handling

+	private IntStack fStateStack = new IntStack();

+	private String valueText = null;

+	boolean foundContentTypeValue = false;

+	private boolean isXHTML;

+

+

+

+	public HTMLHeadTokenizer() {

+		super();

+	}

+

+	  public void reset (Reader in) {

+	  	/* the input device */

+	  	yy_reader = in;

+

+  		/* the current state of the DFA */

+  		yy_state = 0;

+

+  		/* the current lexical state */

+  		yy_lexical_state = YYINITIAL;

+

+  		/* this buffer contains the current text to be matched and is

+  		 the source of the yytext() string */

+  		java.util.Arrays.fill(yy_buffer, (char)0);

+

+  		/* the textposition at the last accepting state */

+  		yy_markedPos = 0;

+

+  		/* the textposition at the last state to be included in yytext */

+  		yy_pushbackPos = 0;

+

+  		/* the current text position in the buffer */

+  		yy_currentPos = 0;

+

+  		/* startRead marks the beginning of the yytext() string in the buffer */

+  		yy_startRead = 0;

+

+  		/** 

+  		 * endRead marks the last character in the buffer, that has been read

+  		 * from input 

+  		 */

+  		yy_endRead = 0;

+

+  		/* number of newlines encountered up to the start of the matched text */

+  		// yyline = 0;

+

+  		/* the number of characters up to the start of the matched text */

+  		yychar = 0;

+

+  		/**

+  		 * the number of characters from the last newline up to the start

+  		 * of the matched text

+  		 */

+  		// yycolumn = 0; 

+

+  		/** 

+  		 * yy_atBOL == true <=> the scanner is currently at the beginning 

+  		 * of a line

+  		 */

+  		yy_atBOL = false;

+

+  		/* yy_atEOF == true <=> the scanner has returned a value for EOF */

+  		yy_atEOF = false;

+

+  		/* denotes if the user-EOF-code has already been executed */

+  		yy_eof_done = false;

+

+

+  		fStateStack.clear();

+  		

+  		hasMore = true;

+  		hasCharsetAttr = false;

+  		isXHTML = false;

+

+		// its a little wasteful to "throw away" first char array generated

+		// by class init (via auto generated code), but we really do want

+		// a small buffer for our head parsers.

+		if (yy_buffer.length != MAX_TO_SCAN) {

+			yy_buffer = new char[MAX_TO_SCAN];

+		}

+  		

+

+  	}

+

+

+	public final HeadParserToken getNextToken() throws IOException {

+		String context = null;

+		HeadParserToken result = null;

+		try {

+			context = primGetNextToken();

+		}

+		catch (IllegalStateException e) {

+			hasMore = false;

+			result = createToken(HTMLHeadTokenizerConstants.UNDEFINED, yychar, yytext());

+			while(yy_advance() != YYEOF) {}

+			return result;

+		}

+		if (valueText != null) {

+			result = createToken(context, yychar, valueText);

+			valueText = null;

+		} else {

+			result = createToken(context, yychar, yytext());

+		}

+		return result;

+	}

+

+	public final boolean hasMoreTokens() {

+		return hasMore && yychar < MAX_TO_SCAN;

+	}

+	private void pushCurrentState() {

+		fStateStack.push(yystate());

+

+	}

+	public final boolean hasCharsetAttr() {

+		return hasCharsetAttr;

+	}

+

+	private void popState() {

+		yybegin(fStateStack.pop());

+	}

+	private HeadParserToken createToken(String context, int start, String text) {

+		return new HeadParserToken(context, start, text);

+	}

+	

+    public boolean isXHTML() {

+       return isXHTML;

+    }

+%}

+

+%eof{

+	hasMore=false;

+%eof}

+

+%public

+%class HTMLHeadTokenizer

+%function primGetNextToken

+%type String

+%char

+%unicode

+%ignorecase 

+//%debug

+%switch

+

+

+UTF16BE = \xFE\xFF

+UTF16LE = \xFF\xFE

+UTF83ByteBOM = \xEF\xBB\xBF

+

+SpaceChar = [\x20\x09]

+

+

+

+// [3] S ::= (0x20 | 0x9 | 0xD | 0xA)+

+S = [\x20\x09\x0D\x0A]

+

+// BeginAttribeValue = {S}* \= {S}*

+

+LineTerminator = \r|\n

+

+Z = (\x00)?

+S_UTF = {Z}{S}{Z}

+BeginAttributeValueUTF = {S_UTF}* \= {S_UTF}*

+

+%state ST_XMLDecl

+%state ST_META_TAG

+%state QuotedAttributeValue

+%state DQ_STRING

+%state SQ_STRING

+%state UnDelimitedString

+%state UnDelimitedCharset

+

+%%

+

+

+<YYINITIAL>  

+{

+	{UTF16BE}   		{hasMore = false; return EncodingParserConstants.UTF16BE;}

+	{UTF16LE}   		{hasMore = false; return EncodingParserConstants.UTF16LE;}

+	{UTF83ByteBOM}   	{hasMore = false; return EncodingParserConstants.UTF83ByteBOM;}

+

+	// force to be started on first line, but we do allow preceeding spaces

+	^ {S_UTF}* ({Z}<{Z}\?{Z}x{Z}m{Z}l{Z}){S_UTF}+ {if (yychar == 0 ) {yybegin(ST_XMLDecl); return XMLHeadTokenizerConstants.XMLDeclStart;}}

+	({Z}<{Z}M{Z}E{Z}T{Z}A{Z})       {yybegin(ST_META_TAG); return HTMLHeadTokenizerConstants.MetaTagStart;}

+	

+	// To determine if content is XHTML.Taken from JSPHeadTokenizer.

+    {Z}<{Z}\!{Z}D{Z}O{Z}C{Z}T{Z}Y{Z}P{Z}E{Z} {S_UTF}* {Z}h{Z}t{Z}m{Z}l{Z} {S_UTF}* {Z}P{Z}U{Z}B{Z}L{Z}I{Z}C{Z} .* {Z}\/{Z}\/{Z}D{Z}T{Z}D{Z}{S_UTF}{Z}X{Z}H{Z}T{Z}M{Z}L{Z}                {isXHTML = true;}

+	{Z}<{Z}h{Z}t{Z}m{Z}l{Z} {S_UTF}* {Z}x{Z}m{Z}l{Z}n{Z}s{Z} {S_UTF}* {Z}\={Z} {S_UTF}* (({Z}\"{Z}) | ({Z}\'{Z})) {Z}h{Z}t{Z}t{Z}p{Z}:{Z}\/{Z}\/{Z}w{Z}w{Z}w{Z}\.{Z}w{Z}3{Z}\.{Z}o{Z}r{Z}g{Z}\/{Z}1{Z}9{Z}9{Z}9{Z}\/{Z}x{Z}h{Z}t{Z}m{Z}l{Z}     {isXHTML = true;}

+

+}	

+	

+<ST_XMLDecl> 

+{

+	//"version" {BeginAttribeValue} {pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDeclVersion;}

+	({Z}e{Z}n{Z}c{Z}o{Z}d{Z}i{Z}n{Z}g{Z}) {BeginAttributeValueUTF} {pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDelEncoding;}

+	// note this "forced end" once end of XML Declaration found

+	({Z}\?{Z}>{Z})    {yybegin(YYINITIAL);  return XMLHeadTokenizerConstants.XMLDeclEnd;}

+}	

+

+<ST_META_TAG> 

+{

+

+//	"http-equiv" {S}* \= {S}* \"? "Content-Type" \"? {S}+ "content" {BeginAttribeValue}  {pushCurrentState(); yybegin(QuotedAttributeValue); foundContentTypeValue=true; return HTMLHeadTokenizerConstants.MetaTagContentType;}

+	{Z}h{Z}t{Z}t{Z}p{Z}-{Z}e{Z}q{Z}u{Z}i{Z}v{Z} {S_UTF}* \= {S_UTF}* {Z}\"?{Z} ({Z}C{Z}o{Z}n{Z}t{Z}e{Z}n{Z}t{Z}-{Z}T{Z}y{Z}p{Z}e{Z}) \"?{Z} ({S_UTF})+ ({Z}c{Z}o{Z}n{Z}t{Z}e{Z}n{Z}t{Z}) {BeginAttributeValueUTF}  {pushCurrentState(); yybegin(QuotedAttributeValue); foundContentTypeValue=true; return HTMLHeadTokenizerConstants.MetaTagContentType;}

+	{Z}c{Z}h{Z}a{Z}r{Z}s{Z}e{Z}t{Z} {BeginAttributeValueUTF} {pushCurrentState(); yybegin(QuotedAttributeValue); foundContentTypeValue=true; hasCharsetAttr=true; return HTMLHeadTokenizerConstants.MetaTagContentType;}

+	{Z}>{Z}    { yybegin(YYINITIAL);  if (foundContentTypeValue) hasMore = false; return HTMLHeadTokenizerConstants.MetaTagEnd;}

+	{Z}\/{Z}>{Z}    { yybegin(YYINITIAL); if (foundContentTypeValue) hasMore = false; return HTMLHeadTokenizerConstants.MetaTagEnd;}

+}

+	

+

+<QuotedAttributeValue>

+{

+	{Z}\"{Z}            { yybegin(DQ_STRING); string.setLength(0); }

+	{Z}\'{Z}			{ yybegin(SQ_STRING); string.setLength(0); }

+	// in this state, anything other than a space character can start an undelimited string

+	{S_UTF}*.           { yypushback(1); yybegin(UnDelimitedString); string.setLength(0);}

+

+}	

+

+

+<DQ_STRING>

+{

+

+	{Z}\"{Z}                      { popState(); valueText = string.toString(); return EncodingParserConstants.StringValue; }

+  	{Z}{LineTerminator}{Z}        { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}\?{Z}>{Z}			{ yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}<{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	

+	{Z}>{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}\/{Z}>{Z}			{ yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	[^\x00]			{ string.append( yytext() ); }

+

+

+}

+

+<SQ_STRING>

+{

+

+	{Z}\'{Z}                      { popState(); valueText = string.toString(); return EncodingParserConstants.StringValue;}

+  	{Z}{LineTerminator}{Z}        { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}%{Z}>{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}<{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}>{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}\/{Z}>{Z}			{ yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	[^\x00]			{ string.append( yytext() ); }

+

+

+}

+

+<UnDelimitedString>

+{

+

+

+	// note this initial special case for HTTP contenttype values

+	// Look ahead and see if there are spaces, but don't append the spaces as they may be double-byte

+	// Let the next state handle removal of the \x00 and properly append spaces

+	";"/{S_UTF}*			{ pushCurrentState(); yybegin(UnDelimitedCharset); string.append( yytext() ); }

+	{S_UTF}                     { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.UnDelimitedStringValue; }

+  	{Z}{LineTerminator}{Z}        { yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}\?{Z}>{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}<{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	// these are a bit special, since we started an undelimit string, but found a quote ... probably indicates a missing beginning quote

+	{Z}\'{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;}

+	{Z}\"{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;}

+	

+	{Z}>{Z}			{ yypushback(yylength());popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	{Z}\/{Z}>{Z}			{ yypushback(yylength()); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}

+	[^\x00]			{ string.append( yytext() ); }

+

+}

+

+<UnDelimitedCharset>

+{

+	{S} { string.append( yytext() ); }

+	// For non \x00 characters, let the previous state handle it

+	[^\x00] {yypushback(1); popState(); }

+}

+

+// The "match anything" rule should always be in effect except for when looking for end of string

+// (That is, remember to update state list if/when new states added)

+.|\n	{if(yychar > MAX_TO_SCAN) {hasMore=false; return EncodingParserConstants.MAX_CHARS_REACHED;}}

+

+// this rule always in effect

+<<EOF>>         {hasMore = false; return EncodingParserConstants.EOF;}

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/HTMLHeadTokenizer.java b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/HTMLHeadTokenizer.java
new file mode 100644
index 0000000..87d6c8f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/HTMLHeadTokenizer.java
@@ -0,0 +1,1206 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+/* The following code was generated by JFlex 1.2.2 on 1/27/04 6:41 PM */
+
+/*nlsXXX*/
+package org.eclipse.wst.common.encoding.contentspecific.html;
+import java.io.IOException;
+import java.io.Reader;
+
+import org.eclipse.wst.common.encoding.contentspecific.EncodingParserConstants;
+import org.eclipse.wst.common.encoding.contentspecific.HeadParserToken;
+import org.eclipse.wst.common.encoding.contentspecific.IntStack;
+import org.eclipse.wst.common.encoding.contentspecific.xml.XMLHeadTokenizerConstants;
+
+
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.informatik.tu-muenchen.de/~kleing/jflex/">JFlex</a> 1.2.2
+ * on 1/27/04 6:41 PM from the specification file
+ * <tt>file:/D:/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/HTMLHeadTokenizer.jflex</tt>
+ */
+public class HTMLHeadTokenizer {
+
+  /** this character denotes the end of file */
+  final public static int YYEOF = -1;
+
+  /** lexical states */
+  final public static int ST_META_TAG = 4;
+  final public static int YYINITIAL = 0;
+  final public static int UnDelimitedString = 12;
+  final public static int DQ_STRING = 8;
+  final public static int SQ_STRING = 10;
+  final public static int ST_XMLDecl = 2;
+  final public static int QuotedAttributeValue = 6;
+
+  /**
+   * YY_LEXSTATE[l] is the state in the DFA for the lexical state l
+   * YY_LEXSTATE[l+1] is the state in the DFA for the lexical state l
+   *                  at the beginning of a line
+   * l is of the form l = 2*k, k a non negative integer
+   */
+  private final static int YY_LEXSTATE[] = { 
+     0,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,  7, 7
+  };
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static String yycmap_packed = 
+    "\11\0\1\6\1\7\2\0\1\11\22\0\1\22\1\0\1\40\2\0"+
+    "\1\44\1\0\1\43\5\0\1\34\1\0\1\42\13\0\1\45\1\12"+
+    "\1\10\1\31\1\13\1\0\1\21\1\0\1\24\1\26\1\17\1\0"+
+    "\1\30\1\32\1\27\2\0\1\16\1\15\1\23\1\25\1\33\1\35"+
+    "\2\0\1\20\1\36\1\37\1\0\1\14\1\41\7\0\1\21\1\0"+
+    "\1\24\1\26\1\17\1\0\1\30\1\32\1\27\2\0\1\16\1\15"+
+    "\1\23\1\25\1\33\1\35\2\0\1\20\1\36\1\37\1\0\1\14"+
+    "\1\41\101\0\1\4\3\0\1\5\17\0\1\3\16\0\1\1\20\0"+
+    "\1\3\16\0\1\1\1\2\170\0\1\2\ufe87\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static char [] yycmap = yy_unpack_cmap(yycmap_packed);
+
+
+  /* error codes */
+  final private static int YY_UNKNOWN_ERROR = 0;
+  final private static int YY_ILLEGAL_STATE = 1;
+  final private static int YY_NO_MATCH = 2;
+  final private static int YY_PUSHBACK_2BIG = 3;
+
+  /* error messages for the codes above */
+  final private static String YY_ERROR_MSG[] = {
+    "Unkown internal scanner error",
+    "Internal error: unknown state",
+    "Error: could not match input",
+    "Error: pushback value was too large"
+  };
+
+  /** the input device */
+  private java.io.Reader yy_reader;
+
+  /** the current state of the DFA */
+  private int yy_state;
+
+  /** the current lexical state */
+  private int yy_lexical_state = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private char yy_buffer[] = new char[16384];
+
+  /** the textposition at the last accepting state */
+  private int yy_markedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int yy_pushbackPos;
+
+  /** the current text position in the buffer */
+  private int yy_currentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int yy_startRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int yy_endRead;
+
+  /** number of newlines encountered up to the start of the matched text */
+  private int yyline;
+
+  /** the number of characters up to the start of the matched text */
+  private int yychar;
+
+  /**
+   * the number of characters from the last newline up to the start of the 
+   * matched text
+   */
+  private int yycolumn; 
+
+  /** 
+   * yy_atBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  private boolean yy_atBOL;
+
+  /** yy_atEOF == true <=> the scanner has returned a value for EOF */
+  private boolean yy_atEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean yy_eof_done;
+
+  /* user code: */
+
+
+	private boolean hasMore = true;
+	private final static int MAX_TO_SCAN = 8000;
+	StringBuffer string = new StringBuffer();
+	// state stack for easier state handling
+	private IntStack fStateStack = new IntStack();
+	private String valueText = null;
+	boolean foundContentTypeValue = false;
+
+
+
+	public HTMLHeadTokenizer() {
+		super();
+	}
+
+	  public void reset (Reader in) {
+	  	/* the input device */
+	  	yy_reader = in;
+
+  		/* the current state of the DFA */
+  		yy_state = 0;
+
+  		/* the current lexical state */
+  		yy_lexical_state = YYINITIAL;
+
+  		/* this buffer contains the current text to be matched and is
+  		 the source of the yytext() string */
+  		java.util.Arrays.fill(yy_buffer, (char)0);
+
+  		/* the textposition at the last accepting state */
+  		yy_markedPos = 0;
+
+  		/* the textposition at the last state to be included in yytext */
+  		yy_pushbackPos = 0;
+
+  		/* the current text position in the buffer */
+  		yy_currentPos = 0;
+
+  		/* startRead marks the beginning of the yytext() string in the buffer */
+  		yy_startRead = 0;
+
+  		/** 
+  		 * endRead marks the last character in the buffer, that has been read
+  		 * from input 
+  		 */
+  		yy_endRead = 0;
+
+  		/* number of newlines encountered up to the start of the matched text */
+  		yyline = 0;
+
+  		/* the number of characters up to the start of the matched text */
+  		yychar = 0;
+
+  		/**
+  		 * the number of characters from the last newline up to the start
+  		 * of the matched text
+  		 */
+  		yycolumn = 0; 
+
+  		/** 
+  		 * yy_atBOL == true <=> the scanner is currently at the beginning 
+  		 * of a line
+  		 */
+  		yy_atBOL = false;
+
+  		/* yy_atEOF == true <=> the scanner has returned a value for EOF */
+  		yy_atEOF = false;
+
+  		/* denotes if the user-EOF-code has already been executed */
+  		yy_eof_done = false;
+
+
+  		fStateStack.clear();
+  		
+  		hasMore = true;
+  		
+		// its a little wasteful to "throw away" first char array generated
+		// by class init (via auto generated code), but we really do want
+		// a small buffer for our head parsers.
+		if (yy_buffer.length != MAX_TO_SCAN) {
+			yy_buffer = new char[MAX_TO_SCAN];
+		}
+  		
+
+  	}
+
+
+	public final HeadParserToken getNextToken() throws IOException {
+		String context = null;
+		context = primGetNextToken();
+		HeadParserToken result = null;
+		if (valueText != null) {
+			result = createToken(context, yychar, valueText);
+			valueText = null;
+		} else {
+			result = createToken(context, yychar, yytext());
+		}
+		return result;
+	}
+
+	public final boolean hasMoreTokens() {
+		return hasMore && yychar < MAX_TO_SCAN;
+	}
+	private void pushCurrentState() {
+		fStateStack.push(yystate());
+
+	}
+
+	private void popState() {
+		yybegin(fStateStack.pop());
+	}
+	private HeadParserToken createToken(String context, int start, String text) {
+		return new HeadParserToken(context, start, text);
+	}
+	
+
+
+
+  /**
+   * Creates a new scanner
+   * There is also a java.io.InputStream version of this constructor.
+   *
+   * @param   in  the java.io.Reader to read input from.
+   */
+  public HTMLHeadTokenizer(java.io.Reader in) {
+    this.yy_reader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  public HTMLHeadTokenizer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] yy_unpack_cmap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 174) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+
+  /**
+   * Gets the next input character.
+   *
+   * @return      the next character of the input stream, EOF if the
+   *              end of the stream is reached.
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  private int yy_advance() throws java.io.IOException {
+
+    /* standard case */
+    if (yy_currentPos < yy_endRead) return yy_buffer[yy_currentPos++];
+
+    /* if the eof is reached, we don't need to work hard */ 
+    if (yy_atEOF) return YYEOF;
+
+    /* otherwise: need to refill the buffer */
+
+    /* first: make room (if you can) */
+    if (yy_startRead > 0) {
+      System.arraycopy(yy_buffer, yy_startRead, 
+                       yy_buffer, 0, 
+                       yy_endRead-yy_startRead);
+
+      /* translate stored positions */
+      yy_endRead-= yy_startRead;
+      yy_currentPos-= yy_startRead;
+      yy_markedPos-= yy_startRead;
+      yy_pushbackPos-= yy_startRead;
+      yy_startRead = 0;
+    }
+
+    /* is the buffer big enough? */
+    if (yy_currentPos >= yy_buffer.length) {
+      /* if not: blow it up */
+      char newBuffer[] = new char[yy_currentPos*2];
+      System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);
+      yy_buffer = newBuffer;
+    }
+
+    /* finally: fill the buffer with new input */
+    int numRead = yy_reader.read(yy_buffer, yy_endRead, 
+                                            yy_buffer.length-yy_endRead);
+
+    if ( numRead == -1 ) return YYEOF;
+
+    yy_endRead+= numRead;
+
+    return yy_buffer[yy_currentPos++];
+  }
+
+
+  /**
+   * Closes the input stream.
+   */
+  final public void yyclose() throws java.io.IOException {
+    yy_atEOF = true;            /* indicate end of file */
+    yy_endRead = yy_startRead;  /* invalidate buffer    */
+    yy_reader.close();
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  final public int yystate() {
+    return yy_lexical_state;
+  }
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  final public void yybegin(int newState) {
+    yy_lexical_state = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  final public String yytext() {
+    return new String( yy_buffer, yy_startRead, yy_markedPos-yy_startRead );
+  }
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  final public int yylength() {
+    return yy_markedPos-yy_startRead;
+  }
+
+
+  /**
+   * Reports an error that occured while scanning.
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void yy_ScanError(int errorCode) {
+    try {
+      System.out.println(YY_ERROR_MSG[errorCode]);
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      System.out.println(YY_ERROR_MSG[YY_UNKNOWN_ERROR]);
+    }
+
+    System.exit(1);
+  } 
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+  private void yypushback(int number) {
+    if ( number > yylength() )
+      yy_ScanError(YY_PUSHBACK_2BIG);
+
+    yy_markedPos -= number;
+  }
+
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void yy_do_eof() {
+    if (!yy_eof_done) {
+      yy_eof_done = true;
+    	hasMore=false;
+
+    }
+  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  public String primGetNextToken() throws java.io.IOException {
+    int yy_input;
+    int yy_action;
+
+
+    while (true) {
+
+      yychar+= yylength();
+
+      yy_atBOL = yy_markedPos <= 0 || yy_buffer[yy_markedPos-1] == '\n';
+      if (!yy_atBOL && yy_buffer[yy_markedPos-1] == '\r') {
+        yy_atBOL = yy_advance() != '\n';
+        if (!yy_atEOF) yy_currentPos--;
+      }
+
+      yy_action = -1;
+
+      yy_currentPos = yy_startRead = yy_markedPos;
+
+      if (yy_atBOL)
+        yy_state = YY_LEXSTATE[yy_lexical_state+1];
+      else
+        yy_state = YY_LEXSTATE[yy_lexical_state];
+
+
+      yy_forAction: {
+        while (true) {
+
+          yy_input = yy_advance();
+
+          if ( yy_input == YYEOF ) break yy_forAction;
+
+          yy_input = yycmap[yy_input];
+
+          boolean yy_isFinal = false;
+          boolean yy_noLookAhead = false;
+
+          yy_forNext: { switch (yy_state) {
+            case 0:
+              switch (yy_input) {
+                case 1: yy_isFinal = true; yy_state = 9; break yy_forNext;
+                case 2: yy_isFinal = true; yy_state = 10; break yy_forNext;
+                case 3: yy_isFinal = true; yy_state = 11; break yy_forNext;
+                case 10: yy_isFinal = true; yy_state = 12; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 8; break yy_forNext;
+              }
+
+            case 1:
+              switch (yy_input) {
+                case 1: yy_isFinal = true; yy_state = 9; break yy_forNext;
+                case 2: yy_isFinal = true; yy_state = 10; break yy_forNext;
+                case 3: yy_isFinal = true; yy_state = 11; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_isFinal = true; yy_state = 13; break yy_forNext;
+                case 10: yy_isFinal = true; yy_state = 14; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 8; break yy_forNext;
+              }
+
+            case 2:
+              switch (yy_input) {
+                case 11: yy_isFinal = true; yy_state = 15; break yy_forNext;
+                case 15: yy_isFinal = true; yy_state = 16; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 8; break yy_forNext;
+              }
+
+            case 3:
+              switch (yy_input) {
+                case 25: yy_isFinal = true; yy_noLookAhead = true; yy_state = 17; break yy_forNext;
+                case 26: yy_isFinal = true; yy_state = 18; break yy_forNext;
+                case 34: yy_isFinal = true; yy_state = 19; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 8; break yy_forNext;
+              }
+
+            case 4:
+              switch (yy_input) {
+                case 6: 
+                case 9: 
+                case 18: yy_isFinal = true; yy_state = 21; break yy_forNext;
+                case 7: yy_isFinal = true; yy_state = 22; break yy_forNext;
+                case 32: yy_isFinal = true; yy_noLookAhead = true; yy_state = 23; break yy_forNext;
+                case 35: yy_isFinal = true; yy_noLookAhead = true; yy_state = 24; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 20; break yy_forNext;
+              }
+
+            case 5:
+              switch (yy_input) {
+                case 7: 
+                case 9: 
+                case 10: 
+                case 25: yy_isFinal = true; yy_noLookAhead = true; yy_state = 26; break yy_forNext;
+                case 11: 
+                case 34: yy_isFinal = true; yy_state = 27; break yy_forNext;
+                case 32: yy_isFinal = true; yy_noLookAhead = true; yy_state = 28; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 25; break yy_forNext;
+              }
+
+            case 6:
+              switch (yy_input) {
+                case 7: 
+                case 9: 
+                case 10: 
+                case 25: yy_isFinal = true; yy_noLookAhead = true; yy_state = 26; break yy_forNext;
+                case 34: yy_isFinal = true; yy_state = 27; break yy_forNext;
+                case 35: yy_isFinal = true; yy_noLookAhead = true; yy_state = 28; break yy_forNext;
+                case 36: yy_isFinal = true; yy_state = 29; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 25; break yy_forNext;
+              }
+
+            case 7:
+              switch (yy_input) {
+                case 10: 
+                case 25: yy_isFinal = true; yy_noLookAhead = true; yy_state = 26; break yy_forNext;
+                case 34: yy_isFinal = true; yy_state = 27; break yy_forNext;
+                case 11: yy_isFinal = true; yy_state = 29; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_isFinal = true; yy_noLookAhead = true; yy_state = 30; break yy_forNext;
+                case 32: 
+                case 35: yy_isFinal = true; yy_noLookAhead = true; yy_state = 31; break yy_forNext;
+                case 37: yy_isFinal = true; yy_state = 32; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 25; break yy_forNext;
+              }
+
+            case 9:
+              switch (yy_input) {
+                case 2: yy_isFinal = true; yy_noLookAhead = true; yy_state = 33; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 10:
+              switch (yy_input) {
+                case 1: yy_isFinal = true; yy_noLookAhead = true; yy_state = 34; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 11:
+              switch (yy_input) {
+                case 4: yy_state = 35; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 12:
+              switch (yy_input) {
+                case 13: yy_state = 36; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 13:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_state = 37; break yy_forNext;
+                case 10: yy_state = 38; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 14:
+              switch (yy_input) {
+                case 13: yy_state = 36; break yy_forNext;
+                case 11: yy_state = 39; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 15:
+              switch (yy_input) {
+                case 25: yy_isFinal = true; yy_noLookAhead = true; yy_state = 40; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 16:
+              switch (yy_input) {
+                case 19: yy_state = 41; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 18:
+              switch (yy_input) {
+                case 16: yy_state = 42; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 19:
+              switch (yy_input) {
+                case 25: yy_isFinal = true; yy_noLookAhead = true; yy_state = 43; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 21:
+              switch (yy_input) {
+                case 6: 
+                case 9: 
+                case 18: yy_isFinal = true; yy_state = 21; break yy_forNext;
+                case 7: yy_state = 44; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 20; break yy_forNext;
+              }
+
+            case 22:
+              switch (yy_input) {
+                case 6: 
+                case 9: 
+                case 18: yy_isFinal = true; yy_state = 21; break yy_forNext;
+                case 7: yy_state = 44; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 20; break yy_forNext;
+              }
+
+            case 27:
+              switch (yy_input) {
+                case 25: yy_isFinal = true; yy_noLookAhead = true; yy_state = 45; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 29:
+              switch (yy_input) {
+                case 25: yy_isFinal = true; yy_noLookAhead = true; yy_state = 46; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 32:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_isFinal = true; yy_state = 32; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 35:
+              switch (yy_input) {
+                case 5: yy_isFinal = true; yy_noLookAhead = true; yy_state = 47; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 36:
+              switch (yy_input) {
+                case 15: yy_state = 48; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 37:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_state = 37; break yy_forNext;
+                case 10: yy_state = 38; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 38:
+              switch (yy_input) {
+                case 11: yy_state = 39; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 39:
+              switch (yy_input) {
+                case 12: yy_state = 49; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 41:
+              switch (yy_input) {
+                case 20: yy_state = 50; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 42:
+              switch (yy_input) {
+                case 16: yy_state = 51; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 44:
+              switch (yy_input) {
+                case 6: 
+                case 9: 
+                case 18: yy_isFinal = true; yy_state = 21; break yy_forNext;
+                case 7: yy_state = 44; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 20; break yy_forNext;
+              }
+
+            case 48:
+              switch (yy_input) {
+                case 16: yy_state = 52; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 49:
+              switch (yy_input) {
+                case 13: yy_state = 53; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 50:
+              switch (yy_input) {
+                case 21: yy_state = 54; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 51:
+              switch (yy_input) {
+                case 27: yy_state = 55; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 52:
+              switch (yy_input) {
+                case 17: yy_state = 56; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 53:
+              switch (yy_input) {
+                case 14: yy_state = 57; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 54:
+              switch (yy_input) {
+                case 22: yy_state = 58; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 55:
+              switch (yy_input) {
+                case 28: yy_state = 59; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 56:
+              switch (yy_input) {
+                case 18: yy_isFinal = true; yy_noLookAhead = true; yy_state = 60; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 57:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_isFinal = true; yy_state = 61; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 58:
+              switch (yy_input) {
+                case 23: yy_state = 62; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 59:
+              switch (yy_input) {
+                case 15: yy_state = 63; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 61:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_isFinal = true; yy_state = 61; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 62:
+              switch (yy_input) {
+                case 19: yy_state = 64; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 63:
+              switch (yy_input) {
+                case 29: yy_state = 65; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 64:
+              switch (yy_input) {
+                case 24: yy_state = 66; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 65:
+              switch (yy_input) {
+                case 30: yy_state = 67; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 66:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_state = 66; break yy_forNext;
+                case 8: yy_isFinal = true; yy_state = 68; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 67:
+              switch (yy_input) {
+                case 23: yy_state = 69; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 68:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_isFinal = true; yy_state = 68; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 69:
+              switch (yy_input) {
+                case 31: yy_state = 70; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 70:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_state = 70; break yy_forNext;
+                case 8: yy_state = 71; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 71:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_state = 71; break yy_forNext;
+                case 20: yy_state = 72; break yy_forNext;
+                case 32: yy_state = 73; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 72:
+              switch (yy_input) {
+                case 21: yy_state = 74; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 73:
+              switch (yy_input) {
+                case 20: yy_state = 72; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 74:
+              switch (yy_input) {
+                case 19: yy_state = 75; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 75:
+              switch (yy_input) {
+                case 16: yy_state = 76; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 76:
+              switch (yy_input) {
+                case 15: yy_state = 77; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 77:
+              switch (yy_input) {
+                case 19: yy_state = 78; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 78:
+              switch (yy_input) {
+                case 16: yy_state = 79; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 79:
+              switch (yy_input) {
+                case 28: yy_state = 80; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 80:
+              switch (yy_input) {
+                case 16: yy_state = 81; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 81:
+              switch (yy_input) {
+                case 33: yy_state = 82; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 82:
+              switch (yy_input) {
+                case 27: yy_state = 83; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 83:
+              switch (yy_input) {
+                case 15: yy_state = 84; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 84:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_state = 85; break yy_forNext;
+                case 32: yy_state = 86; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 85:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_state = 85; break yy_forNext;
+                case 20: yy_state = 87; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 86:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_state = 85; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 87:
+              switch (yy_input) {
+                case 21: yy_state = 88; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 88:
+              switch (yy_input) {
+                case 19: yy_state = 89; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 89:
+              switch (yy_input) {
+                case 16: yy_state = 90; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 90:
+              switch (yy_input) {
+                case 15: yy_state = 91; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 91:
+              switch (yy_input) {
+                case 19: yy_state = 92; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 92:
+              switch (yy_input) {
+                case 16: yy_state = 93; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 93:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_state = 93; break yy_forNext;
+                case 8: yy_isFinal = true; yy_state = 94; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 94:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: 
+                case 18: yy_isFinal = true; yy_state = 94; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            default:
+              yy_ScanError(YY_ILLEGAL_STATE);
+              break;
+          } }
+
+          if ( yy_isFinal ) {
+            yy_action = yy_state; 
+            yy_markedPos = yy_currentPos; 
+            if ( yy_noLookAhead ) break yy_forAction;
+          }
+
+        }
+      }
+
+
+      switch (yy_action) {    
+
+        case 26: 
+          {  yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue; }
+        case 96: break;
+        case 20: 
+        case 21: 
+          {  yypushback(1); yybegin(UnDelimitedString); string.setLength(0); }
+        case 97: break;
+        case 17: 
+          {  yybegin(YYINITIAL);  if (foundContentTypeValue) hasMore = false; return HTMLHeadTokenizerConstants.MetaTagEnd; }
+        case 98: break;
+        case 31: 
+          {  yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue; }
+        case 99: break;
+        case 43: 
+          {  yybegin(YYINITIAL); if (foundContentTypeValue) hasMore = false; return HTMLHeadTokenizerConstants.MetaTagEnd; }
+        case 100: break;
+        case 45: 
+          {  yypushback(2); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue; }
+        case 101: break;
+        case 46: 
+          {  yypushback(2);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue; }
+        case 102: break;
+        case 61: 
+          { if (yychar == 0 ) {yybegin(ST_XMLDecl); return XMLHeadTokenizerConstants.XMLDeclStart;} }
+        case 103: break;
+        case 8: 
+        case 9: 
+        case 10: 
+        case 11: 
+        case 12: 
+        case 13: 
+        case 14: 
+        case 15: 
+        case 16: 
+        case 18: 
+        case 19: 
+        case 22: 
+          { if (yychar > MAX_TO_SCAN) {hasMore=false; return EncodingParserConstants.MAX_CHARS_REACHED;} }
+        case 104: break;
+        case 60: 
+          { yybegin(ST_META_TAG); return HTMLHeadTokenizerConstants.MetaTagStart; }
+        case 105: break;
+        case 40: 
+          { yybegin(YYINITIAL);  return XMLHeadTokenizerConstants.XMLDeclEnd; }
+        case 106: break;
+        case 94: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); foundContentTypeValue=true; return HTMLHeadTokenizerConstants.MetaTagContentType; }
+        case 107: break;
+        case 68: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDelEncoding; }
+        case 108: break;
+        case 33: 
+          { hasMore = false; return EncodingParserConstants.UTF16BE; }
+        case 109: break;
+        case 34: 
+          { hasMore = false; return EncodingParserConstants.UTF16LE; }
+        case 110: break;
+        case 47: 
+          { hasMore = false; return EncodingParserConstants.UTF83ByteBOM; }
+        case 111: break;
+        case 28: 
+          {  popState(); valueText = string.toString(); return EncodingParserConstants.StringValue;  }
+        case 112: break;
+        case 25: 
+        case 27: 
+        case 29: 
+        case 32: 
+          {  string.append( yytext() );  }
+        case 113: break;
+        case 24: 
+          {  yybegin(SQ_STRING); string.setLength(0);  }
+        case 114: break;
+        case 23: 
+          {  yybegin(DQ_STRING); string.setLength(0);  }
+        case 115: break;
+        case 30: 
+          {  yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.UnDelimitedStringValue;  }
+        case 116: break;
+        default: 
+          if (yy_input == YYEOF && yy_startRead == yy_currentPos) {
+            yy_atEOF = true;
+            yy_do_eof();
+              { hasMore = false; return EncodingParserConstants.EOF; }
+          } 
+          else {
+            yy_ScanError(YY_NO_MATCH);
+          }
+      }
+    }
+  }    
+
+  /**
+   * Runs the scanner on input files.
+   *
+   * This main method is the debugging routine for the scanner.
+   * It prints each returned token to System.out until the end of
+   * file is reached, or an error occured.
+   *
+   * @param argv   the command line, contains the filenames to run
+   *               the scanner on.
+   */
+  public static void main(String argv[]) {
+    for (int i = 0; i < argv.length; i++) {
+      HTMLHeadTokenizer scanner = null;
+      try {
+        scanner = new HTMLHeadTokenizer( new java.io.FileReader(argv[i]) );
+      }
+      catch (java.io.FileNotFoundException e) {
+        System.out.println("File not found : \""+argv[i]+"\"");
+        System.exit(1);
+      }
+      catch (java.io.IOException e) {
+        System.out.println("Error opening file \""+argv[i]+"\"");
+        System.exit(1);
+      }
+      catch (ArrayIndexOutOfBoundsException e) {
+        System.out.println("Usage : java HTMLHeadTokenizer <inputfile>");
+        System.exit(1);
+      }
+
+      try {
+        do {
+          System.out.println(scanner.primGetNextToken());
+        } while (!scanner.yy_atEOF);
+
+      }
+      catch (java.io.IOException e) {
+        System.out.println("An I/O error occured while scanning :");
+        System.out.println(e);
+        System.exit(1);
+      }
+      catch (Exception e) {
+        e.printStackTrace();
+        System.exit(1);
+      }
+    }
+  }
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/HTMLHeadTokenizerGenJava.cmd b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/HTMLHeadTokenizerGenJava.cmd
new file mode 100644
index 0000000..96f2325
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/HTMLHeadTokenizerGenJava.cmd
@@ -0,0 +1,23 @@
+@echo off

+

+rem The following variables need to be set/specified for each "development machine"

+set PATH=%PATH%;d:jdks\j2sdk1.4.1_02\bin

+set WORKSPACE_LOCATION=D:\builds\Workspaces\PureHeadWorkspace

+set JFLEX_LIB_LOCATION=D:\DevTimeSupport\JFlex\lib

+

+rem The following variables differ from project to project, but should be otherwise constant

+set MAIN_NAME=HTMLHeadTokenizer

+set PROJECT_SRC=\org.eclipse.wst.common.encoding.contentspecific\src\

+set PACKAGE_DIR=com\ibm\encoding\resource\contentspecific\html\

+

+rem Given the above "framework" and the command themselves, these variables should never need to be modified

+set JAVA_FILE=%MAIN_NAME%.java

+set JFLEX_RULES=%MAIN_NAME%.jflex

+set SKELETON_FILE=%MAIN_NAME%.skeleton

+

+IF EXIST %JAVA_FILE% del %JAVA_FILE%

+rem java -Xmx470000000 -cp %JFLEX_LIB_LOCATION%\sed-jflex.jar;. JFlex.Main %JFLEX_RULES% -skel %SKELETON_FILE% 1>jflexout.txt 2>jflexerr.txt

+java -Xmx470000000 -cp %JFLEX_LIB_LOCATION%\sed-jflex.jar;. JFlex.Main %JFLEX_RULES%  1>jflexout.txt 2>jflexerr.txt

+IF EXIST %JAVA_FILE% copy %JAVA_FILE% %WORKSPACE_LOCATION%%PROJECT_SRC%%PACKAGE_DIR%%JAVA_FILE%

+

+rem pause

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/jflexerr.txt b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/jflexerr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/jflexerr.txt
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/jflexout.txt b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/jflexout.txt
new file mode 100644
index 0000000..1469e9c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/jflexout.txt
@@ -0,0 +1,8 @@
+Reading "HTMLHeadTokenizer.jflex"
+
+Warning : Macro "SpaceChar" has been declared but never used.
+Constructing NFA : 660 states in NFA
+Converting NFA to DFA : 
+.........................................................................................................................
+135 states before minimization, 95 states in minimized DFA
+Writing code to "HTMLHeadTokenizer.java"
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/skeleton b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/skeleton
new file mode 100644
index 0000000..4a9b3f7
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/skeleton
@@ -0,0 +1,268 @@
+

+  /** this character denotes the end of file */

+  final public static int YYEOF = -1;

+

+  /** lexical states */

+---  lexical states, charmap

+

+  /* error codes */

+  final private static int YY_UNKNOWN_ERROR = 0;

+  final private static int YY_ILLEGAL_STATE = 1;

+  final private static int YY_NO_MATCH = 2;

+  final private static int YY_PUSHBACK_2BIG = 3;

+

+  /* error messages for the codes above */

+  final private static String YY_ERROR_MSG[] = {

+    "Unkown internal scanner error",

+    "Internal error: unknown state",

+    "Error: could not match input",

+    "Error: pushback value was too large"

+  };

+

+--- isFinal list

+  /** the input device */

+  private java.io.Reader yy_reader;

+

+  /** the current state of the DFA */

+  private int yy_state;

+

+  /** the current lexical state */

+  private int yy_lexical_state = YYINITIAL;

+

+  /** this buffer contains the current text to be matched and is

+      the source of the yytext() string */

+  private char yy_buffer[] = new char[16384];

+

+  /** the textposition at the last accepting state */

+  private int yy_markedPos;

+

+  /** the textposition at the last state to be included in yytext */

+  private int yy_pushbackPos;

+

+  /** the current text position in the buffer */

+  private int yy_currentPos;

+

+  /** startRead marks the beginning of the yytext() string in the buffer */

+  private int yy_startRead;

+

+  /** endRead marks the last character in the buffer, that has been read

+      from input */

+  private int yy_endRead;

+

+  /** number of newlines encountered up to the start of the matched text */

+  //private int yyline;

+

+  /** the number of characters up to the start of the matched text */

+  private int yychar;

+

+  /**

+   * the number of characters from the last newline up to the start of the 

+   * matched text

+   */

+  //private int yycolumn; 

+

+  /** 

+   * yy_atBOL == true <=> the scanner is currently at the beginning of a line

+   */

+  private boolean yy_atBOL;

+

+  /** yy_atEOF == true <=> the scanner has returned a value for EOF */

+  private boolean yy_atEOF;

+

+--- user class code

+

+  /**

+   * Creates a new scanner

+   * There is also a java.io.InputStream version of this constructor.

+   *

+   * @param   in  the java.io.Reader to read input from.

+   */

+--- constructor declaration

+

+

+  /**

+   * Gets the next input character.

+   *

+   * @return      the next character of the input stream, EOF if the

+   *              end of the stream is reached.

+   * @exception   IOException  if any I/O-Error occurs

+   */

+  private int yy_advance() throws java.io.IOException {

+

+    /* standard case */

+    if (yy_currentPos < yy_endRead) return yy_buffer[yy_currentPos++];

+

+    /* if the eof is reached, we don't need to work hard */ 

+    if (yy_atEOF) return YYEOF;

+

+    /* otherwise: need to refill the buffer */

+

+    /* first: make room (if you can) */

+    if (yy_startRead > 0) {

+      System.arraycopy(yy_buffer, yy_startRead, 

+                       yy_buffer, 0, 

+                       yy_endRead-yy_startRead);

+

+      /* translate stored positions */

+      yy_endRead-= yy_startRead;

+      yy_currentPos-= yy_startRead;

+      yy_markedPos-= yy_startRead;

+      yy_pushbackPos-= yy_startRead;

+      yy_startRead = 0;

+    }

+

+    /* is the buffer big enough? */

+    if (yy_currentPos >= yy_buffer.length) {

+      /* if not: blow it up */

+      char newBuffer[] = new char[yy_currentPos*2];

+      System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);

+      yy_buffer = newBuffer;

+    }

+

+    /* finally: fill the buffer with new input */

+    int numRead = yy_reader.read(yy_buffer, yy_endRead, 

+                                            yy_buffer.length-yy_endRead);

+

+    if ( numRead == -1 ) return YYEOF;

+

+    yy_endRead+= numRead;

+

+    return yy_buffer[yy_currentPos++];

+  }

+

+    

+  /**

+   * Closes the input stream.

+   */

+  final public void yyclose() throws java.io.IOException {

+    yy_atEOF = true;            /* indicate end of file */

+    yy_endRead = yy_startRead;  /* invalidate buffer    */

+    yy_reader.close();

+  }

+

+

+  /**

+   * Returns the current lexical state.

+   */

+  final public int yystate() {

+    return yy_lexical_state;

+  }

+

+  /**

+   * Enters a new lexical state

+   *

+   * @param newState the new lexical state

+   */

+  final public void yybegin(int newState) {

+    yy_lexical_state = newState;

+  }

+

+

+  /**

+   * Returns the text matched by the current regular expression.

+   */

+  final public String yytext() {

+    return new String( yy_buffer, yy_startRead, yy_markedPos-yy_startRead );

+  }

+

+  /**

+   * Returns the length of the matched text region.

+   */

+  final public int yylength() {

+    return yy_markedPos-yy_startRead;

+  }

+

+

+  /**

+   * Reports an error that occured while scanning.

+   *

+   * @param   errorCode  the code of the errormessage to display

+   */

+  private void yy_ScanError(int errorCode) {

+    try {

+      IllegalStateException ise = new IllegalStateException("Instance: " + System.identityHashCode(this) + " offset:" + yychar + " state:" + yystate());

+      System.out.println(YY_ERROR_MSG[errorCode] + "\n" + ise);

+      throw ise;

+    }

+    catch (ArrayIndexOutOfBoundsException e) {

+      System.out.println(YY_ERROR_MSG[YY_UNKNOWN_ERROR]);

+    }

+

+  } 

+

+

+  /**

+   * Pushes the specified amount of characters back into the input stream.

+   *

+   * They will be read again by then next call of the scanning method

+   *

+   * @param number  the number of characters to be read again.

+   *                This number must not be greater than yylength()!

+   */

+  private void yypushback(int number) {

+    if ( number > yylength() )

+      yy_ScanError(YY_PUSHBACK_2BIG);

+

+    yy_markedPos -= number;

+  }

+

+

+--- yy_doEof

+  /**

+   * Resumes scanning until the next regular expression is matched,

+   * the end of input is encountered or an I/O-Error occurs.

+   *

+   * @return      the next token

+   * @exception   IOException  if any I/O-Error occurs

+   */

+--- yylex declaration

+    int yy_input;

+    int yy_action;

+

+--- local declarations

+

+    while (true) {

+

+--- start admin (line, char, col count)

+      yy_action = -1;

+

+      yy_currentPos = yy_startRead = yy_markedPos;

+

+--- start admin (lexstate etc)

+

+      yy_forAction: {

+        while (true) {

+    

+          yy_input = yy_advance();

+

+          if ( yy_input == YYEOF ) break yy_forAction;

+

+--- line, col, char count, next transition, isFinal action

+            yy_action = yy_state; 

+            yy_markedPos = yy_currentPos; 

+--- line count update

+          }

+

+        }

+      }

+

+--- char count update

+

+      switch (yy_action) {    

+

+--- actions

+        default: 

+          if (yy_input == YYEOF && yy_startRead == yy_currentPos) {

+            yy_atEOF = true;

+--- eofvalue

+          } 

+          else {

+--- no match

+          }

+      }

+    }

+  }    

+

+--- main

+

+}

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/skeleton.readme b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/skeleton.readme
new file mode 100644
index 0000000..eb89700
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/HTMLHeadTokenizer/skeleton.readme
@@ -0,0 +1,6 @@
+The skeleton.sed file contains the modified JFlex 1.2.2 skeleton file with

+changes for use with the tokenizers within the org.eclipse.wst.sse.core.xml and

+org.eclipse.wst.sse.core.jsp plugins.

+

+The skeleton file's method definitions are copied into the generated output

+directly.

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/XML10Names.jFlex b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/XML10Names.jFlex
new file mode 100644
index 0000000..d307389
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/XML10Names.jFlex
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2004,2008 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
+ *     kb.huang  - Bug 214416  Dot char is not escaped in XML10Names.jFlex
+ *******************************************************************************/
+/*nlsXXX*/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+%%
+
+%table
+%public
+%final
+%class XML10Names
+%function isValidXML10Name
+%type boolean
+%unicode
+%ignorecase
+%buffer 2048
+%apiprivate
+
+BaseChar = [\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u0131\u0134-\u013E\u0141-\u0148\u014A-\u017E\u0180-\u01C3\u01CD-\u01F0\u01F4-\u01F5\u01FA-\u0217\u0250-\u02A8\u02BB-\u02C1\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03D6\u03DA\u03DC\u03DE\u03E0\u03E2-\u03F3\u0401-\u040C\u040E-\u044F\u0451-\u045C\u045E-\u0481\u0490-\u04C4\u04C7-\u04C8\u04CB-\u04CC\u04D0-\u04EB\u04EE-\u04F5\u04F8-\u04F9\u0531-\u0556\u0559\u0561-\u0586\u05D0-\u05EA\u05F0-\u05F2\u0621-\u063A\u0641-\u064A\u0671-\u06B7\u06BA-\u06BE\u06C0-\u06CE\u06D0-\u06D3\u06D5\u06E5-\u06E6\u0905-\u0939\u093D\u0958-\u0961\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8B\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AE0\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B36-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB5\u0BB7-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CDE\u0CE0-\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D60-\u0D61\u0E01-\u0E2E\u0E30\u0E32-\u0E33\u0E40-\u0E45\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EAE\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0F40-\u0F47\u0F49-\u0F69\u10A0-\u10C5\u10D0-\u10F6\u1100\u1102-\u1103\u1105-\u1107\u1109\u110B-\u110C\u110E-\u1112\u113C\u113E\u1140\u114C\u114E\u1150\u1154-\u1155\u1159\u115F-\u1161\u1163\u1165\u1167\u1169\u116D-\u116E\u1172-\u1173\u1175\u119E\u11A8\u11AB\u11AE-\u11AF\u11B7-\u11B8\u11BA\u11BC-\u11C2\u11EB\u11F0\u11F9\u1E00-\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2126\u212A-\u212B\u212E\u2180-\u2182\u3041-\u3094\u30A1-\u30FA\u3105-\u312C\uAC00-\uD7A3]
+
+Ideographic = [\u4E00-\u9FA5\u3007\u3021-\u3029]
+
+CombiningChar = [\u0300-\u0345\u0360-\u0361\u0483-\u0486\u0591-\u05A1\u05A3-\u05B9\u05BB-\u05BD\u05BF\u05C1-\u05C2\u05C4\u064B-\u0652\u0670\u06D6-\u06DC\u06DD-\u06DF\u06E0-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0901-\u0903\u093C\u093E-\u094C\u094D\u0951-\u0954\u0962-\u0963\u0981-\u0983\u09BC\u09BE\u09BF\u09C0-\u09C4\u09C7-\u09C8\u09CB-\u09CD\u09D7\u09E2-\u09E3\u0A02\u0A3C\u0A3E\u0A3F\u0A40-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A70-\u0A71\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0B01-\u0B03\u0B3C\u0B3E-\u0B43\u0B47-\u0B48\u0B4B-\u0B4D\u0B56-\u0B57\u0B82-\u0B83\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C01-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56\u0C82-\u0C83\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5-\u0CD6\u0D02-\u0D03\u0D3E-\u0D43\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86-\u0F8B\u0F90-\u0F95\u0F97\u0F99-\u0FAD\u0FB1-\u0FB7\u0FB9\u20D0-\u20DC\u20E1\u302A-\u302F\u3099\u309A]
+
+Digit =  [\u0030-\u0039\u0660-\u0669\u06F0-\u06F9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE7-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29]
+
+Extender = [\u00B7\u02D0\u02D1\u0387\u0640\u0E46\u0EC6\u3005\u3031-\u3035\u309D-\u309E\u30FC-\u30FE]
+
+Letter = ({BaseChar} | {Ideographic})
+
+NameChar = ({Letter} | {Digit} | "." | "-" | "_" | ":" | {CombiningChar} | {Extender})
+
+Name = ({Letter} | "_" | ":" ) ({NameChar})*
+
+
+
+%{
+        boolean result;
+        /**
+         * Creates a new scanner
+         */
+        public XML10Names() {
+                this.zzReader = null;
+        }
+
+        public boolean isValidXML10Name(String stringToCheck) {
+                boolean result = false;
+                yyreset(new java.io.StringReader(stringToCheck));
+                try {
+                        result = isValidXML10Name();
+                }
+                catch (java.io.IOException e) {
+                        // should be impossible with strings, but if occurs, just means
+                        // "not"
+                        result = false;
+                }
+                return result;
+        }
+
+%}
+
+
+
+
+%%
+
+<YYINITIAL>
+{
+
+        // name must be whole line (input), not partial
+        // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=214416
+        {Name}            {return true; /* exact name */}
+        {Name}.+          {return false; /* more than name */}
+
+        // match anything (else) should normally come last
+        .                 {return false; /* matched wild */}
+
+}
+
+
+// this rule always in effect
+<<EOF>>
+{
+        {return false; /* hit end with no match */}
+}
+
+
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/XML10Names.java b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/XML10Names.java
new file mode 100644
index 0000000..fe91212
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/XML10Names.java
@@ -0,0 +1,595 @@
+/* The following code was generated by JFlex 1.4 on 2/25/08 10:25 AM */
+
+/*******************************************************************************
+ * Copyright (c) 2004,2008 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
+ *     kb.huang  - Bug 214416  Dot char is not escaped in XML10Names.jFlex
+ *******************************************************************************/
+/*nlsXXX*/
+package org.eclipse.wst.xml.core.internal.parser;
+
+
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.jflex.de/">JFlex</a> 1.4
+ * on 2/25/08 10:25 AM from the specification file
+ * <tt>XML10Names.jflex</tt>
+ */
+public final class XML10Names {
+
+  /** This character denotes the end of file */
+  private static final int YYEOF = -1;
+
+  /** initial size of the lookahead buffer */
+  private static final int ZZ_BUFFERSIZE = 2048;
+
+  /** lexical states */
+  private static final int YYINITIAL = 0;
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final String ZZ_CMAP_PACKED = 
+    "\12\0\1\3\42\0\1\2\1\2\1\0\12\2\1\1\6\0\32\1"+
+    "\4\0\1\1\1\0\32\1\74\0\1\2\10\0\27\1\1\0\37\1"+
+    "\1\0\72\1\2\0\13\1\2\0\10\1\1\0\65\1\1\0\104\1"+
+    "\11\0\44\1\3\0\2\1\4\0\36\1\70\0\131\1\22\0\7\1"+
+    "\16\0\2\2\56\0\106\2\32\0\2\2\44\0\1\1\1\2\3\1"+
+    "\1\0\1\1\1\0\24\1\1\0\54\1\1\0\7\1\3\0\1\1"+
+    "\1\0\1\1\1\0\1\1\1\0\1\1\1\0\22\1\15\0\14\1"+
+    "\1\0\102\1\1\0\14\1\1\0\44\1\1\0\4\2\11\0\65\1"+
+    "\2\0\2\1\2\0\2\1\3\0\34\1\2\0\10\1\2\0\2\1"+
+    "\67\0\46\1\2\0\1\1\7\0\46\1\12\0\21\2\1\0\27\2"+
+    "\1\0\3\2\1\0\1\2\1\0\2\2\1\0\1\2\13\0\33\1"+
+    "\5\0\3\1\56\0\32\1\5\0\1\2\12\1\10\2\15\0\12\2"+
+    "\6\0\1\2\107\1\2\0\5\1\1\0\17\1\1\0\4\1\1\0"+
+    "\1\1\17\2\2\1\2\2\1\0\4\2\2\0\12\2\u0207\0\3\2"+
+    "\1\0\65\1\2\0\1\2\1\1\20\2\3\0\4\2\3\0\12\1"+
+    "\2\2\2\0\12\2\21\0\3\2\1\0\10\1\2\0\2\1\2\0"+
+    "\26\1\1\0\7\1\1\0\1\1\3\0\4\1\2\0\1\2\1\0"+
+    "\7\2\2\0\2\2\2\0\3\2\11\0\1\2\4\0\2\1\1\0"+
+    "\3\1\2\2\2\0\12\2\2\1\20\0\1\2\2\0\6\1\4\0"+
+    "\2\1\2\0\26\1\1\0\7\1\1\0\2\1\1\0\2\1\1\0"+
+    "\2\1\2\0\1\2\1\0\5\2\4\0\2\2\2\0\3\2\13\0"+
+    "\4\1\1\0\1\1\7\0\12\2\2\2\3\1\14\0\3\2\1\0"+
+    "\7\1\1\0\1\1\1\0\3\1\1\0\26\1\1\0\7\1\1\0"+
+    "\2\1\1\0\5\1\2\0\1\2\1\1\10\2\1\0\3\2\1\0"+
+    "\3\2\22\0\1\1\5\0\12\2\21\0\3\2\1\0\10\1\2\0"+
+    "\2\1\2\0\26\1\1\0\7\1\1\0\2\1\2\0\4\1\2\0"+
+    "\1\2\1\1\6\2\3\0\2\2\2\0\3\2\10\0\2\2\4\0"+
+    "\2\1\1\0\3\1\4\0\12\2\22\0\2\2\1\0\6\1\3\0"+
+    "\3\1\1\0\4\1\3\0\2\1\1\0\1\1\1\0\2\1\3\0"+
+    "\2\1\3\0\3\1\3\0\10\1\1\0\3\1\4\0\5\2\3\0"+
+    "\3\2\1\0\4\2\11\0\1\2\17\0\11\2\21\0\3\2\1\0"+
+    "\10\1\1\0\3\1\1\0\27\1\1\0\12\1\1\0\5\1\4\0"+
+    "\7\2\1\0\3\2\1\0\4\2\7\0\2\2\11\0\2\1\4\0"+
+    "\12\2\22\0\2\2\1\0\10\1\1\0\3\1\1\0\27\1\1\0"+
+    "\12\1\1\0\5\1\4\0\7\2\1\0\3\2\1\0\4\2\7\0"+
+    "\2\2\7\0\1\1\1\0\2\1\4\0\12\2\22\0\2\2\1\0"+
+    "\10\1\1\0\3\1\1\0\27\1\1\0\20\1\4\0\6\2\2\0"+
+    "\3\2\1\0\4\2\11\0\1\2\10\0\2\1\4\0\12\2\221\0"+
+    "\56\1\1\0\1\1\1\2\2\1\7\2\5\0\6\1\1\2\10\2"+
+    "\1\0\12\2\47\0\2\1\1\0\1\1\2\0\2\1\1\0\1\1"+
+    "\2\0\1\1\6\0\4\1\1\0\7\1\1\0\3\1\1\0\1\1"+
+    "\1\0\1\1\2\0\2\1\1\0\2\1\1\0\1\1\1\2\2\1"+
+    "\6\2\1\0\2\2\1\1\2\0\5\1\1\0\1\2\1\0\6\2"+
+    "\2\0\12\2\76\0\2\2\6\0\12\2\13\0\1\2\1\0\1\2"+
+    "\1\0\1\2\4\0\2\2\10\1\1\0\41\1\7\0\24\2\1\0"+
+    "\6\2\4\0\6\2\1\0\1\2\1\0\25\2\3\0\7\2\1\0"+
+    "\1\2\346\0\46\1\12\0\47\1\11\0\1\1\1\0\2\1\1\0"+
+    "\3\1\1\0\1\1\1\0\2\1\1\0\5\1\51\0\1\1\1\0"+
+    "\1\1\1\0\1\1\13\0\1\1\1\0\1\1\1\0\1\1\3\0"+
+    "\2\1\3\0\1\1\5\0\3\1\1\0\1\1\1\0\1\1\1\0"+
+    "\1\1\1\0\1\1\3\0\2\1\3\0\2\1\1\0\1\1\50\0"+
+    "\1\1\11\0\1\1\2\0\1\1\2\0\2\1\7\0\2\1\1\0"+
+    "\1\1\1\0\7\1\50\0\1\1\4\0\1\1\10\0\1\1\u0c06\0"+
+    "\234\1\4\0\132\1\6\0\26\1\2\0\6\1\2\0\46\1\2\0"+
+    "\6\1\2\0\10\1\1\0\1\1\1\0\1\1\1\0\1\1\1\0"+
+    "\37\1\2\0\65\1\1\0\7\1\1\0\1\1\3\0\3\1\1\0"+
+    "\7\1\3\0\4\1\2\0\6\1\4\0\15\1\5\0\3\1\1\0"+
+    "\7\1\323\0\15\2\4\0\1\2\104\0\1\1\3\0\2\1\2\0"+
+    "\1\1\121\0\3\1\u0e82\0\1\2\1\0\1\1\31\0\11\1\6\2"+
+    "\1\0\5\2\13\0\124\1\4\0\2\2\2\0\2\2\2\0\132\1"+
+    "\1\0\3\2\6\0\50\1\u1cd3\0\u51a6\1\u0c5a\0\u2ba4\1\u285c\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
+
+  /** 
+   * Translates DFA states to action switch labels.
+   */
+  private static final int [] ZZ_ACTION = zzUnpackAction();
+
+  private static final String ZZ_ACTION_PACKED_0 =
+    "\1\0\1\1\1\2\1\3";
+
+  private static int [] zzUnpackAction() {
+    int [] result = new int[4];
+    int offset = 0;
+    offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAction(String packed, int offset, int [] result) {
+    int i = 0;       /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+
+  /** 
+   * Translates a state to a row index in the transition table
+   */
+  private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
+
+  private static final String ZZ_ROWMAP_PACKED_0 =
+    "\0\0\0\4\0\10\0\14";
+
+  private static int [] zzUnpackRowMap() {
+    int [] result = new int[4];
+    int offset = 0;
+    offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackRowMap(String packed, int offset, int [] result) {
+    int i = 0;  /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int high = packed.charAt(i++) << 16;
+      result[j++] = high | packed.charAt(i++);
+    }
+    return j;
+  }
+
+  /** 
+   * The transition table of the DFA
+   */
+  private static final int ZZ_TRANS [] = {
+    1, 2, 1, -1, -1, -1, -1, -1, 3, 2, 
+    2, -1, 3, 3, 3, -1
+  };
+
+  /* error codes */
+  private static final int ZZ_UNKNOWN_ERROR = 0;
+  private static final int ZZ_NO_MATCH = 1;
+  private static final int ZZ_PUSHBACK_2BIG = 2;
+
+  /* error messages for the codes above */
+  private static final String ZZ_ERROR_MSG[] = {
+    "Unkown internal scanner error",
+    "Error: could not match input",
+    "Error: pushback value was too large"
+  };
+
+  /**
+   * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+   */
+  private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
+
+  private static final String ZZ_ATTRIBUTE_PACKED_0 =
+    "\1\0\1\11\2\1";
+
+  private static int [] zzUnpackAttribute() {
+    int [] result = new int[4];
+    int offset = 0;
+    offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
+    return result;
+  }
+
+  private static int zzUnpackAttribute(String packed, int offset, int [] result) {
+    int i = 0;       /* index in packed string  */
+    int j = offset;  /* index in unpacked array */
+    int l = packed.length();
+    while (i < l) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      do result[j++] = value; while (--count > 0);
+    }
+    return j;
+  }
+
+  /** the input device */
+  private java.io.Reader zzReader;
+
+  /** the current state of the DFA */
+  private int zzState;
+
+  /** the current lexical state */
+  private int zzLexicalState = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
+
+  /** the textposition at the last accepting state */
+  private int zzMarkedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int zzPushbackPos;
+
+  /** the current text position in the buffer */
+  private int zzCurrentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int zzStartRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int zzEndRead;
+
+  /** number of newlines encountered up to the start of the matched text */
+  private int yyline;
+
+  /** the number of characters up to the start of the matched text */
+  private int yychar;
+
+  /**
+   * the number of characters from the last newline up to the start of the 
+   * matched text
+   */
+  private int yycolumn;
+
+  /** 
+   * zzAtBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  private boolean zzAtBOL = true;
+
+  /** zzAtEOF == true <=> the scanner is at the EOF */
+  private boolean zzAtEOF;
+
+  /* user code: */
+        boolean result;
+        /**
+         * Creates a new scanner
+         */
+        public XML10Names() {
+                this.zzReader = null;
+        }
+
+        public boolean isValidXML10Name(String stringToCheck) {
+                boolean result = false;
+                yyreset(new java.io.StringReader(stringToCheck));
+                try {
+                        result = isValidXML10Name();
+                }
+                catch (java.io.IOException e) {
+                        // should be impossible with strings, but if occurs, just means
+                        // "not"
+                        result = false;
+                }
+                return result;
+        }
+
+
+
+  /**
+   * Creates a new scanner
+   * There is also a java.io.InputStream version of this constructor.
+   *
+   * @param   in  the java.io.Reader to read input from.
+   */
+  public XML10Names(java.io.Reader in) {
+    this.zzReader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  public XML10Names(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] zzUnpackCMap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 1218) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+
+  /**
+   * Refills the input buffer.
+   *
+   * @return      <code>false</code>, iff there was new input.
+   * 
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  private boolean zzRefill() throws java.io.IOException {
+
+    /* first: make room (if you can) */
+    if (zzStartRead > 0) {
+      System.arraycopy(zzBuffer, zzStartRead,
+                       zzBuffer, 0,
+                       zzEndRead-zzStartRead);
+
+      /* translate stored positions */
+      zzEndRead-= zzStartRead;
+      zzCurrentPos-= zzStartRead;
+      zzMarkedPos-= zzStartRead;
+      zzPushbackPos-= zzStartRead;
+      zzStartRead = 0;
+    }
+
+    /* is the buffer big enough? */
+    if (zzCurrentPos >= zzBuffer.length) {
+      /* if not: blow it up */
+      char newBuffer[] = new char[zzCurrentPos*2];
+      System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length);
+      zzBuffer = newBuffer;
+    }
+
+    /* finally: fill the buffer with new input */
+    int numRead = zzReader.read(zzBuffer, zzEndRead,
+                                            zzBuffer.length-zzEndRead);
+
+    if (numRead < 0) {
+      return true;
+    }
+    else {
+      zzEndRead+= numRead;
+      return false;
+    }
+  }
+
+    
+  /**
+   * Closes the input stream.
+   */
+  private final void yyclose() throws java.io.IOException {
+    zzAtEOF = true;            /* indicate end of file */
+    zzEndRead = zzStartRead;  /* invalidate buffer    */
+
+    if (zzReader != null)
+      zzReader.close();
+  }
+
+
+  /**
+   * Resets the scanner to read from a new input stream.
+   * Does not close the old reader.
+   *
+   * All internal variables are reset, the old input stream 
+   * <b>cannot</b> be reused (internal buffer is discarded and lost).
+   * Lexical state is set to <tt>ZZ_INITIAL</tt>.
+   *
+   * @param reader   the new input stream 
+   */
+  private final void yyreset(java.io.Reader reader) {
+    zzReader = reader;
+    zzAtBOL  = true;
+    zzAtEOF  = false;
+    zzEndRead = zzStartRead = 0;
+    zzCurrentPos = zzMarkedPos = zzPushbackPos = 0;
+    yyline = yychar = yycolumn = 0;
+    zzLexicalState = YYINITIAL;
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  private final int yystate() {
+    return zzLexicalState;
+  }
+
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  private final void yybegin(int newState) {
+    zzLexicalState = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  private final String yytext() {
+    return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead );
+  }
+
+
+  /**
+   * Returns the character at position <tt>pos</tt> from the 
+   * matched text. 
+   * 
+   * It is equivalent to yytext().charAt(pos), but faster
+   *
+   * @param pos the position of the character to fetch. 
+   *            A value from 0 to yylength()-1.
+   *
+   * @return the character at position pos
+   */
+  private final char yycharat(int pos) {
+    return zzBuffer[zzStartRead+pos];
+  }
+
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  private final int yylength() {
+    return zzMarkedPos-zzStartRead;
+  }
+
+
+  /**
+   * Reports an error that occured while scanning.
+   *
+   * In a wellformed scanner (no or only correct usage of 
+   * yypushback(int) and a match-all fallback rule) this method 
+   * will only be called with things that "Can't Possibly Happen".
+   * If this method is called, something is seriously wrong
+   * (e.g. a JFlex bug producing a faulty scanner etc.).
+   *
+   * Usual syntax/scanner level error handling should be done
+   * in error fallback rules.
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void zzScanError(int errorCode) {
+    String message;
+    try {
+      message = ZZ_ERROR_MSG[errorCode];
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
+    }
+
+    throw new Error(message);
+  } 
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+  private void yypushback(int number)  {
+    if ( number > yylength() )
+      zzScanError(ZZ_PUSHBACK_2BIG);
+
+    zzMarkedPos -= number;
+  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   java.io.IOException  if any I/O-Error occurs
+   */
+  private boolean isValidXML10Name() throws java.io.IOException {
+    int zzInput;
+    int zzAction;
+
+    // cached fields:
+    int zzCurrentPosL;
+    int zzMarkedPosL;
+    int zzEndReadL = zzEndRead;
+    char [] zzBufferL = zzBuffer;
+    char [] zzCMapL = ZZ_CMAP;
+
+    int [] zzTransL = ZZ_TRANS;
+    int [] zzRowMapL = ZZ_ROWMAP;
+    int [] zzAttrL = ZZ_ATTRIBUTE;
+
+    while (true) {
+      zzMarkedPosL = zzMarkedPos;
+
+      zzAction = -1;
+
+      zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+  
+      zzState = zzLexicalState;
+
+
+      zzForAction: {
+        while (true) {
+    
+          if (zzCurrentPosL < zzEndReadL)
+            zzInput = zzBufferL[zzCurrentPosL++];
+          else if (zzAtEOF) {
+            zzInput = YYEOF;
+            break zzForAction;
+          }
+          else {
+            // store back cached positions
+            zzCurrentPos  = zzCurrentPosL;
+            zzMarkedPos   = zzMarkedPosL;
+            boolean eof = zzRefill();
+            // get translated positions and possibly new buffer
+            zzCurrentPosL  = zzCurrentPos;
+            zzMarkedPosL   = zzMarkedPos;
+            zzBufferL      = zzBuffer;
+            zzEndReadL     = zzEndRead;
+            if (eof) {
+              zzInput = YYEOF;
+              break zzForAction;
+            }
+            else {
+              zzInput = zzBufferL[zzCurrentPosL++];
+            }
+          }
+          int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ];
+          if (zzNext == -1) break zzForAction;
+          zzState = zzNext;
+
+          int zzAttributes = zzAttrL[zzState];
+          if ( (zzAttributes & 1) == 1 ) {
+            zzAction = zzState;
+            zzMarkedPosL = zzCurrentPosL;
+            if ( (zzAttributes & 8) == 8 ) break zzForAction;
+          }
+
+        }
+      }
+
+      // store back cached position
+      zzMarkedPos = zzMarkedPosL;
+
+      switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+        case 1: 
+          { return false; /* matched wild */
+          }
+        case 4: break;
+        case 2: 
+          { return true; /* exact name */
+          }
+        case 5: break;
+        case 3: 
+          { return false; /* more than name */
+          }
+        case 6: break;
+        default: 
+          if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+            zzAtEOF = true;
+              { {return false; /* hit end with no match */} }
+          } 
+          else {
+            zzScanError(ZZ_NO_MATCH);
+          }
+      }
+    }
+  }
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/XML10NamesGenJavaJFlex14.cmd b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/XML10NamesGenJavaJFlex14.cmd
new file mode 100644
index 0000000..7c816d0
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/XML10NamesGenJavaJFlex14.cmd
@@ -0,0 +1,25 @@
+@echo on

+

+rem The following variables need to be set/specified for each "development machine"

+set PATH=%PATH%;D:\JDKs\ibm-java2-sdk-50-win-i386\bin

+set WORKSPACE_LOCATION=D:\builds\Workspaces\newWTPpurehead

+set JFLEX_LIB_LOCATION=D:\DevTimeSupport\JFlex-1.4\lib

+

+rem The following variables differ from project to project, but should be otherwise constant

+set MAIN_NAME=XML10Names

+

+set PROJECT_SRC=\org.eclipse.wst.xml.core\src\

+set PACKAGE_DIR=org\eclipse\wst\xml\core\internal\parser\

+

+

+rem Given the above "framework" and the command themselves, these variables should never need to be modified

+set JAVA_FILE=%MAIN_NAME%.java

+set JFLEX_RULES=%MAIN_NAME%.jflex

+set SKELETON_FILE=%MAIN_NAME%.skeleton

+

+IF EXIST %JAVA_FILE% del %JAVA_FILE%

+rem java -Xmx470000000 -cp %JFLEX_LIB_LOCATION%\Jflex.jar;. JFlex.Main %JFLEX_RULES% -skel %SKELETON_FILE% 1>jflexout.txt 2>jflexerr.txt

+java -Xmx470000000 -cp %JFLEX_LIB_LOCATION%\Jflex.jar;. JFlex.Main %JFLEX_RULES%  1>jflexout.txt 2>jflexerr.txt

+IF EXIST %JAVA_FILE% copy %JAVA_FILE% %WORKSPACE_LOCATION%%PROJECT_SRC%%PACKAGE_DIR%%JAVA_FILE%

+

+pause

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/jflexerr.txt b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/jflexerr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/jflexerr.txt
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/jflexout.txt b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/jflexout.txt
new file mode 100644
index 0000000..c336f12
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XML10Names/jflexout.txt
@@ -0,0 +1,6 @@
+Reading "XML10Names.jflex"
+Constructing NFA : 84 states in NFA
+Converting NFA to DFA : 
+............
+14 states before minimization, 4 states in minimized DFA
+Writing code to "XML10Names.java"
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/XMLHeadTokenizer.jFlex b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/XMLHeadTokenizer.jFlex
new file mode 100644
index 0000000..d6fe899
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/XMLHeadTokenizer.jFlex
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/*nlsXXX*/
+package org.eclipse.wst.common.encoding.contentspecific.xml;
+import java.io.IOException;
+import java.io.Reader;
+
+import org.eclipse.wst.common.encoding.contentspecific.EncodingParserConstants;
+import org.eclipse.wst.common.encoding.contentspecific.HeadParserToken;
+import org.eclipse.wst.common.encoding.contentspecific.IntStack;
+import org.eclipse.wst.common.encoding.contentspecific.xml.XMLHeadTokenizerConstants;
+
+
+
+
+%%
+
+%{
+
+
+	private boolean hasMore = true;
+	private final static int MAX_TO_SCAN = 8000;
+	StringBuffer string = new StringBuffer();
+	// state stack for easier state handling
+	private IntStack fStateStack = new IntStack();
+	private String valueText = null;
+
+
+	public XMLHeadTokenizer() {
+		super();
+	}
+
+	  public void reset (Reader in) {
+                /* the input device */
+                zzReader = in;
+
+                /* the current state of the DFA */
+                zzState = 0;
+
+                /* the current lexical state */
+                zzLexicalState = YYINITIAL;
+
+                /* this buffer contains the current text to be matched and is
+                 the source of the yytext() string */
+                java.util.Arrays.fill(zzBuffer, (char)0);
+
+                /* the textposition at the last accepting state */
+                zzMarkedPos = 0;
+
+                /* the textposition at the last state to be included in yytext */
+                zzPushbackPos = 0;
+
+                /* the current text position in the buffer */
+                zzCurrentPos = 0;
+
+                /* startRead marks the beginning of the yytext() string in the buffer */
+                zzStartRead = 0;
+
+                /**
+                 * endRead marks the last character in the buffer, that has been read
+                 * from input
+                 */
+                zzEndRead = 0;
+
+                /* number of newlines encountered up to the start of the matched text */
+                yyline = 0;
+
+                /* the number of characters up to the start of the matched text */
+                yychar = 0;
+
+                /**
+                 * the number of characters from the last newline up to the start
+                 * of the matched text
+                 */
+                yycolumn = 0;
+
+                /**
+                 * yy_atBOL == true <=> the scanner is currently at the beginning
+                 * of a line
+                 */
+                zzAtBOL = true;
+
+                /* yy_atEOF == true <=> the scanner has returned a value for EOF */
+                zzAtEOF = false;
+
+                /* denotes if the user-EOF-code has already been executed */
+                zzEOFDone = false;
+
+
+                fStateStack.clear();
+
+                hasMore = true;
+  		
+  	}
+
+
+	public final HeadParserToken getNextToken() throws IOException {
+		String context = null;
+		context = primGetNextToken();
+		HeadParserToken result = null;
+		if (valueText != null) {
+			result = createToken(context, yychar, valueText);
+			valueText = null;
+		} else {
+			result = createToken(context, yychar, yytext());
+		}
+		return result;
+	}
+
+	public final boolean hasMoreTokens() {
+		return hasMore && yychar < MAX_TO_SCAN;
+	}
+	private void pushCurrentState() {
+		fStateStack.push(yystate());
+
+	}
+
+	private void popState() {
+		yybegin(fStateStack.pop());
+	}
+	
+	private HeadParserToken createToken(String context, int start, String text) {
+		return new HeadParserToken(context, start, text);
+	}	
+
+%}
+
+%eof{
+	hasMore=false;
+%eof}
+
+%public
+%class XMLHeadTokenizer
+%function primGetNextToken
+%type String
+%char
+%unicode
+%ignorecase 
+//%debug
+%switch
+%buffer 8192
+
+UTF16BE = \xFE\xFF
+UTF16LE = \xFF\xFE
+UTF83ByteBOM = \xEF\xBB\xBF
+
+SpaceChar = [\x20\x09]
+
+// [3] S ::= (0x20 | 0x9 | 0xD | 0xA)+
+S = [\x20\x09\x0D\x0A]
+
+BeginAttribeValue = {S}* \= {S}*
+
+LineTerminator = \r|\n
+
+
+%state ST_XMLDecl
+%state QuotedAttributeValue
+%state DQ_STRING
+%state SQ_STRING
+%state UnDelimitedString
+
+%%
+
+
+<YYINITIAL>  
+{
+	// force to start at beginning of line (^) and at beginning of file (yychar == 0)
+	^{UTF16BE}   		{if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF16BE;}}
+	^{UTF16LE}   		{if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF16LE;}}
+	^{UTF83ByteBOM}   	{if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF83ByteBOM;}}
+	
+	// force to be started on first line, but we do allow preceeding spaces
+	^ {S}* "<\?xml" {S}+ {if (yychar == 0 ) {yybegin(ST_XMLDecl); return XMLHeadTokenizerConstants.XMLDeclStart;}}
+	
+}	
+	
+<ST_XMLDecl> 
+{
+	"version" {BeginAttribeValue} {pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDeclVersion;}
+	"encoding" {BeginAttribeValue} {pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDelEncoding;}
+	// note the "forced end" (via 'hasMore=false') once the end of XML Declaration found
+	// This is since non-ascii chars may follow and may cause IOExceptions which would not occur once stream is 
+	// read with incorrect encoding (such as if platform encoding is in effect until true encoding detected). 
+	"\?>"    {yybegin(YYINITIAL); hasMore = false; return XMLHeadTokenizerConstants.XMLDeclEnd;}
+}	
+
+	
+
+<QuotedAttributeValue>
+{
+	\"                      { yybegin(DQ_STRING); string.setLength(0); }
+	\'			{ yybegin(SQ_STRING); string.setLength(0); }
+	// in this state, anything other than a space character can start an undelimited string
+	{S}*.           { yypushback(1); yybegin(UnDelimitedString); string.setLength(0);}
+
+}	
+
+
+<DQ_STRING>
+{
+
+	\"                      { popState(); valueText = string.toString(); return EncodingParserConstants.StringValue; }
+  	{LineTerminator}        { yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}
+	"\?>"			{ yypushback(2); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}
+	'<'			{ yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}
+	.			{ string.append( yytext() ); }
+
+
+}
+
+<SQ_STRING>
+{
+
+	\'                      { popState(); valueText = string.toString(); return EncodingParserConstants.StringValue;}
+  	{LineTerminator}        { yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}
+	"%>"			{ yypushback(2);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}
+	'<'			{ yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}
+	.			{ string.append( yytext() ); }
+
+
+}
+
+<UnDelimitedString>
+{
+
+	{S}                     { yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.UnDelimitedStringValue; }
+  	{LineTerminator}        { yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}
+	"\?>"			{ yypushback(2);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}
+	'<'	
+	{ yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}
+	// these are a bit special, since we started an undelimit string, but found a quote ... probably indicates a missing beginning quote
+	\'			{ yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;}
+	
+	\"			{ yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue;}
+	
+	.			{ string.append( yytext() ); }
+
+}
+
+// The "match anything" rule should always be in effect except for when looking for end of string
+// (That is, remember to update state list if/when new states added)
+<YYINITIAL, ST_XMLDecl, QuotedAttributeValue>
+{
+// this is the fallback (match "anything") rule  (for this scanner, input is ignored, and position advanced, if not recognized)
+.|\n              {if (yychar > MAX_TO_SCAN) {hasMore=false; return EncodingParserConstants.MAX_CHARS_REACHED;}}
+}
+
+// this rule always in effect
+<<EOF>>         {hasMore = false; return EncodingParserConstants.EOF;}
+
+	
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/XMLHeadTokenizer.java b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/XMLHeadTokenizer.java
new file mode 100644
index 0000000..b353067
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/XMLHeadTokenizer.java
@@ -0,0 +1,905 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+/* The following code was generated by JFlex 1.2.2 on 4/6/04 11:13 PM */
+
+/*nlsXXX*/
+package org.eclipse.wst.common.encoding.contentspecific.xml;
+import java.io.IOException;
+import java.io.Reader;
+
+import org.eclipse.wst.common.encoding.contentspecific.EncodingParserConstants;
+import org.eclipse.wst.common.encoding.contentspecific.HeadParserToken;
+import org.eclipse.wst.common.encoding.contentspecific.IntStack;
+import org.eclipse.wst.common.encoding.contentspecific.xml.XMLHeadTokenizerConstants;
+
+
+
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.informatik.tu-muenchen.de/~kleing/jflex/">JFlex</a> 1.2.2
+ * on 4/6/04 11:13 PM from the specification file
+ * <tt>file:/D:/DevTimeSupport/HeadParsers/XMLHeadTokenizer/XMLHeadTokenizer.jflex</tt>
+ */
+public class XMLHeadTokenizer {
+
+  /** this character denotes the end of file */
+  final public static int YYEOF = -1;
+
+  /** lexical states */
+  final public static int YYINITIAL = 0;
+  final public static int UnDelimitedString = 10;
+  final public static int DQ_STRING = 6;
+  final public static int SQ_STRING = 8;
+  final public static int ST_XMLDecl = 2;
+  final public static int QuotedAttributeValue = 4;
+
+  /**
+   * YY_LEXSTATE[l] is the state in the DFA for the lexical state l
+   * YY_LEXSTATE[l+1] is the state in the DFA for the lexical state l
+   *                  at the beginning of a line
+   * l is of the form l = 2*k, k a non negative integer
+   */
+  private final static int YY_LEXSTATE[] = { 
+     0,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6, 6
+  };
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static String yycmap_packed = 
+    "\11\0\1\6\1\7\2\0\1\11\22\0\1\6\1\0\1\27\2\0"+
+    "\1\31\1\0\1\30\24\0\1\12\1\10\1\26\1\13\3\0\1\21"+
+    "\1\23\1\17\1\0\1\25\1\0\1\24\2\0\1\16\1\15\1\20"+
+    "\1\22\10\0\1\14\12\0\1\21\1\23\1\17\1\0\1\25\1\0"+
+    "\1\24\2\0\1\16\1\15\1\20\1\22\10\0\1\14\102\0\1\4"+
+    "\3\0\1\5\17\0\1\3\16\0\1\1\20\0\1\3\16\0\1\1"+
+    "\1\2\170\0\1\2\ufe87\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static char [] yycmap = yy_unpack_cmap(yycmap_packed);
+
+
+  /* error codes */
+  final private static int YY_UNKNOWN_ERROR = 0;
+  final private static int YY_ILLEGAL_STATE = 1;
+  final private static int YY_NO_MATCH = 2;
+  final private static int YY_PUSHBACK_2BIG = 3;
+
+  /* error messages for the codes above */
+  final private static String YY_ERROR_MSG[] = {
+    "Unkown internal scanner error",
+    "Internal error: unknown state",
+    "Error: could not match input",
+    "Error: pushback value was too large"
+  };
+
+  /** the input device */
+  private java.io.Reader yy_reader;
+
+  /** the current state of the DFA */
+  private int yy_state;
+
+  /** the current lexical state */
+  private int yy_lexical_state = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private char yy_buffer[] = new char[16384];
+
+  /** the textposition at the last accepting state */
+  private int yy_markedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int yy_pushbackPos;
+
+  /** the current text position in the buffer */
+  private int yy_currentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int yy_startRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int yy_endRead;
+
+  /** number of newlines encountered up to the start of the matched text */
+  private int yyline;
+
+  /** the number of characters up to the start of the matched text */
+  private int yychar;
+
+  /**
+   * the number of characters from the last newline up to the start of the 
+   * matched text
+   */
+  private int yycolumn; 
+
+  /** 
+   * yy_atBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  private boolean yy_atBOL;
+
+  /** yy_atEOF == true <=> the scanner has returned a value for EOF */
+  private boolean yy_atEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean yy_eof_done;
+
+  /* user code: */
+
+
+	private boolean hasMore = true;
+	private final static int MAX_TO_SCAN = 8000;
+	StringBuffer string = new StringBuffer();
+	// state stack for easier state handling
+	private IntStack fStateStack = new IntStack();
+	private String valueText = null;
+
+
+	public XMLHeadTokenizer() {
+		super();
+	}
+
+	  public void reset (Reader in) {
+	  	/* the input device */
+	  	yy_reader = in;
+
+  		/* the current state of the DFA */
+  		yy_state = 0;
+
+  		/* the current lexical state */
+  		yy_lexical_state = YYINITIAL;
+
+  		/* this buffer contains the current text to be matched and is
+  		 the source of the yytext() string */
+  		java.util.Arrays.fill(yy_buffer, (char)0);
+
+  		/* the textposition at the last accepting state */
+  		yy_markedPos = 0;
+
+  		/* the textposition at the last state to be included in yytext */
+  		yy_pushbackPos = 0;
+
+  		/* the current text position in the buffer */
+  		yy_currentPos = 0;
+
+  		/* startRead marks the beginning of the yytext() string in the buffer */
+  		yy_startRead = 0;
+
+  		/** 
+  		 * endRead marks the last character in the buffer, that has been read
+  		 * from input 
+  		 */
+  		yy_endRead = 0;
+
+  		/* number of newlines encountered up to the start of the matched text */
+  		yyline = 0;
+
+  		/* the number of characters up to the start of the matched text */
+  		yychar = 0;
+
+  		/**
+  		 * the number of characters from the last newline up to the start
+  		 * of the matched text
+  		 */
+  		yycolumn = 0; 
+
+  		/** 
+  		 * yy_atBOL == true <=> the scanner is currently at the beginning 
+  		 * of a line
+  		 */
+  		yy_atBOL = false;
+
+  		/* yy_atEOF == true <=> the scanner has returned a value for EOF */
+  		yy_atEOF = false;
+
+  		/* denotes if the user-EOF-code has already been executed */
+  		yy_eof_done = false;
+
+
+  		fStateStack.clear();
+  		
+  		hasMore = true;
+  		
+  		// its a little wasteful to "throw away" first char array generated
+  		// by class init (via auto generated code), but we really do want 
+  		// a small buffer for our head parsers. 
+  		if (yy_buffer.length != MAX_TO_SCAN) {
+  			yy_buffer = new char[MAX_TO_SCAN];
+  		}
+
+
+  	}
+
+
+	public final HeadParserToken getNextToken() throws IOException {
+		String context = null;
+		context = primGetNextToken();
+		HeadParserToken result = null;
+		if (valueText != null) {
+			result = createToken(context, yychar, valueText);
+			valueText = null;
+		} else {
+			result = createToken(context, yychar, yytext());
+		}
+		return result;
+	}
+
+	public final boolean hasMoreTokens() {
+		return hasMore && yychar < MAX_TO_SCAN;
+	}
+	private void pushCurrentState() {
+		fStateStack.push(yystate());
+
+	}
+
+	private void popState() {
+		yybegin(fStateStack.pop());
+	}
+	
+	private HeadParserToken createToken(String context, int start, String text) {
+		return new HeadParserToken(context, start, text);
+	}	
+
+
+
+  /**
+   * Creates a new scanner
+   * There is also a java.io.InputStream version of this constructor.
+   *
+   * @param   in  the java.io.Reader to read input from.
+   */
+  public XMLHeadTokenizer(java.io.Reader in) {
+    this.yy_reader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  public XMLHeadTokenizer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] yy_unpack_cmap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 128) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+
+  /**
+   * Gets the next input character.
+   *
+   * @return      the next character of the input stream, EOF if the
+   *              end of the stream is reached.
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  private int yy_advance() throws java.io.IOException {
+
+    /* standard case */
+    if (yy_currentPos < yy_endRead) return yy_buffer[yy_currentPos++];
+
+    /* if the eof is reached, we don't need to work hard */ 
+    if (yy_atEOF) return YYEOF;
+
+    /* otherwise: need to refill the buffer */
+
+    /* first: make room (if you can) */
+    if (yy_startRead > 0) {
+      System.arraycopy(yy_buffer, yy_startRead, 
+                       yy_buffer, 0, 
+                       yy_endRead-yy_startRead);
+
+      /* translate stored positions */
+      yy_endRead-= yy_startRead;
+      yy_currentPos-= yy_startRead;
+      yy_markedPos-= yy_startRead;
+      yy_pushbackPos-= yy_startRead;
+      yy_startRead = 0;
+    }
+
+    /* is the buffer big enough? */
+    if (yy_currentPos >= yy_buffer.length) {
+      /* if not: blow it up */
+      char newBuffer[] = new char[yy_currentPos*2];
+      System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);
+      yy_buffer = newBuffer;
+    }
+
+    /* finally: fill the buffer with new input */
+    int numRead = yy_reader.read(yy_buffer, yy_endRead, 
+                                            yy_buffer.length-yy_endRead);
+
+    if ( numRead == -1 ) return YYEOF;
+
+    yy_endRead+= numRead;
+
+    return yy_buffer[yy_currentPos++];
+  }
+
+
+  /**
+   * Closes the input stream.
+   */
+  final public void yyclose() throws java.io.IOException {
+    yy_atEOF = true;            /* indicate end of file */
+    yy_endRead = yy_startRead;  /* invalidate buffer    */
+    yy_reader.close();
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  final public int yystate() {
+    return yy_lexical_state;
+  }
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  final public void yybegin(int newState) {
+    yy_lexical_state = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  final public String yytext() {
+    return new String( yy_buffer, yy_startRead, yy_markedPos-yy_startRead );
+  }
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  final public int yylength() {
+    return yy_markedPos-yy_startRead;
+  }
+
+
+  /**
+   * Reports an error that occured while scanning.
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void yy_ScanError(int errorCode) {
+    try {
+      System.out.println(YY_ERROR_MSG[errorCode]);
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      System.out.println(YY_ERROR_MSG[YY_UNKNOWN_ERROR]);
+    }
+
+    System.exit(1);
+  } 
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+  private void yypushback(int number) {
+    if ( number > yylength() )
+      yy_ScanError(YY_PUSHBACK_2BIG);
+
+    yy_markedPos -= number;
+  }
+
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void yy_do_eof() {
+    if (!yy_eof_done) {
+      yy_eof_done = true;
+    	hasMore=false;
+
+    }
+  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  public String primGetNextToken() throws java.io.IOException {
+    int yy_input;
+    int yy_action;
+
+
+    while (true) {
+
+      yychar+= yylength();
+
+      yy_atBOL = yy_markedPos <= 0 || yy_buffer[yy_markedPos-1] == '\n';
+      if (!yy_atBOL && yy_buffer[yy_markedPos-1] == '\r') {
+        yy_atBOL = yy_advance() != '\n';
+        if (!yy_atEOF) yy_currentPos--;
+      }
+
+      yy_action = -1;
+
+      yy_currentPos = yy_startRead = yy_markedPos;
+
+      if (yy_atBOL)
+        yy_state = YY_LEXSTATE[yy_lexical_state+1];
+      else
+        yy_state = YY_LEXSTATE[yy_lexical_state];
+
+
+      yy_forAction: {
+        while (true) {
+
+          yy_input = yy_advance();
+
+          if ( yy_input == YYEOF ) break yy_forAction;
+
+          yy_input = yycmap[yy_input];
+
+          boolean yy_isFinal = false;
+          boolean yy_noLookAhead = false;
+
+          yy_forNext: { switch (yy_state) {
+            case 0:
+              switch (yy_input) {
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 7; break yy_forNext;
+              }
+
+            case 1:
+              switch (yy_input) {
+                case 1: yy_isFinal = true; yy_state = 8; break yy_forNext;
+                case 2: yy_isFinal = true; yy_state = 9; break yy_forNext;
+                case 3: yy_isFinal = true; yy_state = 10; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 9: yy_isFinal = true; yy_state = 11; break yy_forNext;
+                case 10: yy_isFinal = true; yy_state = 12; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 7; break yy_forNext;
+              }
+
+            case 2:
+              switch (yy_input) {
+                case 11: yy_isFinal = true; yy_state = 13; break yy_forNext;
+                case 15: yy_isFinal = true; yy_state = 14; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 7; break yy_forNext;
+              }
+
+            case 3:
+              switch (yy_input) {
+                case 6: 
+                case 9: yy_isFinal = true; yy_state = 16; break yy_forNext;
+                case 7: yy_isFinal = true; yy_state = 17; break yy_forNext;
+                case 23: yy_isFinal = true; yy_noLookAhead = true; yy_state = 18; break yy_forNext;
+                case 24: yy_isFinal = true; yy_noLookAhead = true; yy_state = 19; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 15; break yy_forNext;
+              }
+
+            case 4:
+              switch (yy_input) {
+                case 7: 
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 21; break yy_forNext;
+                case 11: yy_isFinal = true; yy_state = 22; break yy_forNext;
+                case 23: yy_isFinal = true; yy_noLookAhead = true; yy_state = 23; break yy_forNext;
+                case 24: yy_isFinal = true; yy_state = 24; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 20; break yy_forNext;
+              }
+
+            case 5:
+              switch (yy_input) {
+                case 7: 
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 21; break yy_forNext;
+                case 24: yy_isFinal = true; yy_state = 25; break yy_forNext;
+                case 25: yy_isFinal = true; yy_state = 26; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 20; break yy_forNext;
+              }
+
+            case 6:
+              switch (yy_input) {
+                case 11: yy_isFinal = true; yy_state = 26; break yy_forNext;
+                case 6: 
+                case 7: 
+                case 9: yy_isFinal = true; yy_noLookAhead = true; yy_state = 27; break yy_forNext;
+                case 23: yy_isFinal = true; yy_noLookAhead = true; yy_state = 28; break yy_forNext;
+                case 24: yy_isFinal = true; yy_state = 29; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 20; break yy_forNext;
+              }
+
+            case 8:
+              switch (yy_input) {
+                case 2: yy_isFinal = true; yy_noLookAhead = true; yy_state = 30; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 9:
+              switch (yy_input) {
+                case 1: yy_isFinal = true; yy_noLookAhead = true; yy_state = 31; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 10:
+              switch (yy_input) {
+                case 4: yy_state = 32; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 11:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: yy_state = 33; break yy_forNext;
+                case 10: yy_state = 34; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 12:
+              switch (yy_input) {
+                case 11: yy_state = 35; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 13:
+              switch (yy_input) {
+                case 22: yy_isFinal = true; yy_noLookAhead = true; yy_state = 36; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 14:
+              switch (yy_input) {
+                case 16: yy_state = 37; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 16:
+              switch (yy_input) {
+                case 6: 
+                case 9: yy_isFinal = true; yy_state = 16; break yy_forNext;
+                case 7: yy_state = 38; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 15; break yy_forNext;
+              }
+
+            case 17:
+              switch (yy_input) {
+                case 6: 
+                case 9: yy_isFinal = true; yy_state = 16; break yy_forNext;
+                case 7: yy_state = 38; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 15; break yy_forNext;
+              }
+
+            case 22:
+              switch (yy_input) {
+                case 22: yy_isFinal = true; yy_noLookAhead = true; yy_state = 39; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 24:
+              switch (yy_input) {
+                case 10: yy_state = 40; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 25:
+              switch (yy_input) {
+                case 10: yy_state = 40; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 26:
+              switch (yy_input) {
+                case 22: yy_isFinal = true; yy_noLookAhead = true; yy_state = 41; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 29:
+              switch (yy_input) {
+                case 10: yy_state = 40; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 32:
+              switch (yy_input) {
+                case 5: yy_isFinal = true; yy_noLookAhead = true; yy_state = 42; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 33:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: yy_state = 33; break yy_forNext;
+                case 10: yy_state = 34; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 34:
+              switch (yy_input) {
+                case 11: yy_state = 35; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 35:
+              switch (yy_input) {
+                case 12: yy_state = 43; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 37:
+              switch (yy_input) {
+                case 17: yy_state = 44; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 38:
+              switch (yy_input) {
+                case 6: 
+                case 9: yy_isFinal = true; yy_state = 16; break yy_forNext;
+                case 7: yy_state = 38; break yy_forNext;
+                default: yy_isFinal = true; yy_noLookAhead = true; yy_state = 15; break yy_forNext;
+              }
+
+            case 40:
+              switch (yy_input) {
+                case 24: yy_isFinal = true; yy_noLookAhead = true; yy_state = 21; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 43:
+              switch (yy_input) {
+                case 13: yy_state = 45; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 44:
+              switch (yy_input) {
+                case 18: yy_state = 46; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 45:
+              switch (yy_input) {
+                case 14: yy_state = 47; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 46:
+              switch (yy_input) {
+                case 19: yy_state = 48; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 47:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: yy_isFinal = true; yy_state = 49; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 48:
+              switch (yy_input) {
+                case 20: yy_state = 50; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 49:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: yy_isFinal = true; yy_state = 49; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 50:
+              switch (yy_input) {
+                case 16: yy_state = 51; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 51:
+              switch (yy_input) {
+                case 21: yy_state = 52; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 52:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: yy_state = 52; break yy_forNext;
+                case 8: yy_isFinal = true; yy_state = 53; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            case 53:
+              switch (yy_input) {
+                case 6: 
+                case 7: 
+                case 9: yy_isFinal = true; yy_state = 53; break yy_forNext;
+                default: break yy_forAction;
+              }
+
+            default:
+              yy_ScanError(YY_ILLEGAL_STATE);
+              break;
+          } }
+
+          if ( yy_isFinal ) {
+            yy_action = yy_state; 
+            yy_markedPos = yy_currentPos; 
+            if ( yy_noLookAhead ) break yy_forAction;
+          }
+
+        }
+      }
+
+
+      switch (yy_action) {    
+
+        case 25: 
+          {  popState(); valueText = string.toString(); return EncodingParserConstants.StringValue; }
+        case 55: break;
+        case 21: 
+          {  yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue; }
+        case 56: break;
+        case 15: 
+        case 16: 
+          {  yypushback(1); yybegin(UnDelimitedString); string.setLength(0); }
+        case 57: break;
+        case 28: 
+        case 29: 
+          {  yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTermintatedUnDelimitedStringValue; }
+        case 58: break;
+        case 39: 
+          {  yypushback(2); popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue; }
+        case 59: break;
+        case 41: 
+          {  yypushback(2);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue; }
+        case 60: break;
+        case 7: 
+        case 8: 
+        case 9: 
+        case 10: 
+        case 11: 
+        case 12: 
+        case 13: 
+        case 14: 
+        case 17: 
+          { if (yychar > MAX_TO_SCAN) {hasMore=false; return EncodingParserConstants.MAX_CHARS_REACHED;} }
+        case 61: break;
+        case 30: 
+          { if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF16BE;} }
+        case 62: break;
+        case 31: 
+          { if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF16LE;} }
+        case 63: break;
+        case 42: 
+          { if (yychar == 0 ) {hasMore = false; return EncodingParserConstants.UTF83ByteBOM;} }
+        case 64: break;
+        case 49: 
+          { if (yychar == 0 ) {yybegin(ST_XMLDecl); return XMLHeadTokenizerConstants.XMLDeclStart;} }
+        case 65: break;
+        case 36: 
+          { yybegin(YYINITIAL); hasMore = false; return XMLHeadTokenizerConstants.XMLDeclEnd; }
+        case 66: break;
+        case 53: 
+          { pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDelEncoding; }
+        case 67: break;
+        case 23: 
+          {  popState(); valueText = string.toString(); return EncodingParserConstants.StringValue;  }
+        case 68: break;
+        case 20: 
+        case 22: 
+        case 24: 
+        case 26: 
+          {  string.append( yytext() );  }
+        case 69: break;
+        case 19: 
+          {  yybegin(SQ_STRING); string.setLength(0);  }
+        case 70: break;
+        case 18: 
+          {  yybegin(DQ_STRING); string.setLength(0);  }
+        case 71: break;
+        case 27: 
+          {  yypushback(1);popState(); valueText = string.toString(); return EncodingParserConstants.UnDelimitedStringValue;  }
+        case 72: break;
+        default: 
+          if (yy_input == YYEOF && yy_startRead == yy_currentPos) {
+            yy_atEOF = true;
+            yy_do_eof();
+              { hasMore = false; return EncodingParserConstants.EOF; }
+          } 
+          else {
+            yy_ScanError(YY_NO_MATCH);
+          }
+      }
+    }
+  }    
+
+  /**
+   * Runs the scanner on input files.
+   *
+   * This main method is the debugging routine for the scanner.
+   * It prints each returned token to System.out until the end of
+   * file is reached, or an error occured.
+   *
+   * @param argv   the command line, contains the filenames to run
+   *               the scanner on.
+   */
+  public static void main(String argv[]) {
+    for (int i = 0; i < argv.length; i++) {
+      XMLHeadTokenizer scanner = null;
+      try {
+        scanner = new XMLHeadTokenizer( new java.io.FileReader(argv[i]) );
+      }
+      catch (java.io.FileNotFoundException e) {
+        System.out.println("File not found : \""+argv[i]+"\"");
+        System.exit(1);
+      }
+      catch (java.io.IOException e) {
+        System.out.println("Error opening file \""+argv[i]+"\"");
+        System.exit(1);
+      }
+      catch (ArrayIndexOutOfBoundsException e) {
+        System.out.println("Usage : java XMLHeadTokenizer <inputfile>");
+        System.exit(1);
+      }
+
+      try {
+        do {
+          System.out.println(scanner.primGetNextToken());
+        } while (!scanner.yy_atEOF);
+
+      }
+      catch (java.io.IOException e) {
+        System.out.println("An I/O error occured while scanning :");
+        System.out.println(e);
+        System.exit(1);
+      }
+      catch (Exception e) {
+        e.printStackTrace();
+        System.exit(1);
+      }
+    }
+  }
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/XMLHeadTokenizerGenJava.cmd b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/XMLHeadTokenizerGenJava.cmd
new file mode 100644
index 0000000..7ec1c7b
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/XMLHeadTokenizerGenJava.cmd
@@ -0,0 +1,28 @@
+@echo on

+

+rem The following variables need to be set/specified for each "development machine"

+set PATH=%PATH%;D:\JDKs\j2sdk1.4.2_03\bin

+set WORKSPACE_LOCATION=D:\builds\Workspaces\WSWBM8

+set JFLEX_LIB_LOCATION=D:\DevTimeSupport\JFlex\lib

+

+rem The following variables differ from project to project, but should be otherwise constant

+set MAIN_NAME=XMLHeadTokenizer

+

+rem set PROJECT_SRC=\org.eclipse.wst.sse.core.xml\src\

+rem set PACKAGE_DIR=com\ibm\sse\model\xml\encoding\

+

+set PROJECT_SRC=\org.eclipse.wst.common.encoding.contentspecific\src\

+set PACKAGE_DIR=com\ibm\encoding\resource\contentspecific\xml\

+

+

+rem Given the above "framework" and the command themselves, these variables should never need to be modified

+set JAVA_FILE=%MAIN_NAME%.java

+set JFLEX_RULES=%MAIN_NAME%.jflex

+set SKELETON_FILE=%MAIN_NAME%.skeleton

+

+IF EXIST %JAVA_FILE% del %JAVA_FILE%

+rem java -Xmx470000000 -cp %JFLEX_LIB_LOCATION%\sed-jflex.jar;. JFlex.Main %JFLEX_RULES% -skel %SKELETON_FILE% 1>jflexout.txt 2>jflexerr.txt

+java -Xmx470000000 -cp %JFLEX_LIB_LOCATION%\sed-jflex.jar;. JFlex.Main %JFLEX_RULES%  1>jflexout.txt 2>jflexerr.txt

+IF EXIST %JAVA_FILE% copy %JAVA_FILE% %WORKSPACE_LOCATION%%PROJECT_SRC%%PACKAGE_DIR%%JAVA_FILE%

+

+pause

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/jflexerr.txt b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/jflexerr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/jflexerr.txt
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/jflexout.txt b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/jflexout.txt
new file mode 100644
index 0000000..316c32e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/jflexout.txt
@@ -0,0 +1,8 @@
+Reading "XMLHeadTokenizer.jflex"
+
+Warning : Macro "SpaceChar" has been declared but never used.
+Constructing NFA : 358 states in NFA
+Converting NFA to DFA : 
+...................................................................
+79 states before minimization, 54 states in minimized DFA
+Writing code to "XMLHeadTokenizer.java"
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/oldXMLHeadTokenizer.skeleton b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/oldXMLHeadTokenizer.skeleton
new file mode 100644
index 0000000..9809602
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/HeadParsers/XMLHeadTokenizer/oldXMLHeadTokenizer.skeleton
@@ -0,0 +1,263 @@
+

+  /** this character denotes the end of file */

+  final public static int YYEOF = -1;

+

+  /** lexical states */

+---  lexical states, charmap

+

+  /* error codes */

+  final private static int YY_UNKNOWN_ERROR = 0;

+  final private static int YY_ILLEGAL_STATE = 1;

+  final private static int YY_NO_MATCH = 2;

+  final private static int YY_PUSHBACK_2BIG = 3;

+

+  /* error messages for the codes above */

+  final private static String YY_ERROR_MSG[] = {

+    "Unkown internal scanner error",		//$NON-NLS-1$

+    "Internal error: unknown state",		//$NON-NLS-1$

+    "Error: could not match input",		//$NON-NLS-1$

+    "Error: pushback value was too large"	//$NON-NLS-1$

+  };

+

+--- isFinal list

+  /** the input device */

+  private java.io.Reader yy_reader;

+

+  /** the current state of the DFA */

+  private int yy_state;

+

+  /** the current lexical state */

+  private int yy_lexical_state = YYINITIAL;

+

+  /** this buffer contains the current text to be matched and is

+      the source of the yytext() string */

+  private char yy_buffer[] = new char[16384];

+

+  /** the textposition at the last accepting state */

+  private int yy_markedPos;

+

+  /** the textposition at the last state to be included in yytext */

+  private int yy_pushbackPos;

+

+  /** the current text position in the buffer */

+  private int yy_currentPos;

+

+  /** startRead marks the beginning of the yytext() string in the buffer */

+  private int yy_startRead;

+

+  /** endRead marks the last character in the buffer, that has been read

+      from input */

+  private int yy_endRead;

+

+  /** number of newlines encountered up to the start of the matched text */

+  private int yyline;

+

+  /** the number of characters up to the start of the matched text */

+  private int yychar;

+

+  

+  /** yy_atEOF == true <=> the scanner has returned a value for EOF */

+  private boolean yy_atEOF;

+

+	// state stack for handling embedded regions

+	private IntStack fStateStack = new IntStack();

+

+

+--- user class code

+

+  /**

+   * Creates a new scanner

+   * There is also a java.io.InputStream version of this constructor.

+   *

+   * @param   in  the java.io.Reader to read input from.

+   */

+--- constructor declaration

+

+

+  /**

+   * Gets the next input character.

+   *

+   * @return      the next character of the input stream, EOF if the

+   *              end of the stream is reached.

+   * @exception   IOException  if any I/O-Error occurs

+   */

+  private int yy_advance() throws java.io.IOException {

+

+    /* standard case */

+    if (yy_currentPos < yy_endRead) return yy_buffer[yy_currentPos++];

+

+    /* if the eof is reached, we don't need to work hard */ 

+    if (yy_atEOF) return YYEOF;

+

+    /* otherwise: need to refill the buffer */

+

+    /* first: make room (if you can) */

+    if (yy_startRead > 0) {

+      System.arraycopy(yy_buffer, yy_startRead, 

+                       yy_buffer, 0, 

+                       yy_endRead-yy_startRead);

+

+      /* translate stored positions */

+      yy_endRead-= yy_startRead;

+      yy_currentPos-= yy_startRead;

+      yy_markedPos-= yy_startRead;

+      yy_pushbackPos-= yy_startRead;

+      yy_startRead = 0;

+    }

+

+    /* is the buffer big enough? */

+    if (yy_currentPos >= yy_buffer.length) {

+      /* if not: blow it up */

+      char newBuffer[] = new char[yy_currentPos*2];

+      System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);

+      yy_buffer = newBuffer;

+    }

+

+    /* finally: fill the buffer with new input */

+    int numRead = yy_reader.read(yy_buffer, yy_endRead, 

+                                            yy_buffer.length-yy_endRead);

+

+    if ( numRead == -1 ) return YYEOF;

+

+    yy_endRead+= numRead;

+

+    return yy_buffer[yy_currentPos++];

+  }

+

+    

+  /**

+   * Closes the input stream.

+   */

+  final public void yyclose() throws java.io.IOException {

+    yy_atEOF = true;            /* indicate end of file */

+    yy_endRead = yy_startRead;  /* invalidate buffer    */

+    yy_reader.close();

+  }

+

+

+  /**

+   * Returns the current lexical state.

+   */

+  final public int yystate() {

+    return yy_lexical_state;

+  }

+

+  /**

+   * Enters a new lexical state

+   *

+   * @param newState the new lexical state

+   */

+  final public void yybegin(int newState) {

+    yy_lexical_state = newState;

+  }

+

+

+  /**

+   * Returns the text matched by the current regular expression.

+   */

+  final public String yytext() {

+    return new String( yy_buffer, yy_startRead, yy_markedPos-yy_startRead );

+  }

+

+  /**

+   * Returns the length of the matched text region.

+   */

+  final public int yylength() {

+    return yy_markedPos-yy_startRead;

+  }

+

+

+  /**

+   * Reports an error that occured while scanning - from the SED JFlex skeleton

+   *

+   * @param   errorCode  the code of the errormessage to display

+   */

+  private void yy_ScanError(int errorCode) {

+    try {

+      //Logger.log(Logger.ERROR, YY_ERROR_MSG[errorCode]);

+	System.out.println("ScanError: " + errorCode + ": " + YY_ERROR_MSG[errorCode]);

+    }

+    catch (ArrayIndexOutOfBoundsException e) {

+      //Logger.log(Logger.ERROR, YY_ERROR_MSG[YY_UNKNOWN_ERROR]);

+	System.out.println("ScanError: " + errorCode + ": " + YY_ERROR_MSG[YY_UNKNOWN_ERROR]);

+   }

+    // DO NOT EXIT the VM on an error

+    // System.exit(1);

+  } 

+

+

+  /**

+   * Pushes the specified amount of characters back into the input stream.

+   *

+   * They will be read again by then next call of the scanning method

+   *

+   * @param number  the number of characters to be read again.

+   *                This number must not be greater than yylength()!

+   */

+  private void yypushback(int number) {

+    if ( number > yylength() )

+      yy_ScanError(YY_PUSHBACK_2BIG);

+

+    yy_markedPos -= number;

+  }

+

+

+--- yy_doEof

+  /**

+   * Resumes scanning until the next regular expression is matched,

+   * the end of input is encountered or an I/O-Error occurs.

+   *

+   * @return      the next token

+   * @exception   IOException  if any I/O-Error occurs

+   */

+--- yylex declaration

+    int yy_input;

+    int yy_action;

+

+--- local declarations

+

+    while (true) {

+

+--- start admin (line, char, col count)

+      yy_action = -1;

+

+      yy_currentPos = yy_startRead = yy_markedPos;

+

+--- start admin (lexstate etc)

+

+      yy_forAction: {

+        while (true) {

+    

+          yy_input = yy_advance();

+

+          if ( yy_input == YYEOF ) break yy_forAction;

+

+--- line, col, char count, next transition, isFinal action

+            yy_action = yy_state; 

+            yy_markedPos = yy_currentPos; 

+--- line count update

+          }

+

+        }

+      }

+

+--- char count update

+

+      switch (yy_action) {    

+

+--- actions

+        default: 

+          if (yy_input == YYEOF && yy_startRead == yy_currentPos) {

+            yy_atEOF = true;

+--- eofvalue

+          } 

+          else {

+--- no match

+          }

+      }

+    }

+  }    

+

+--- main

+

+}

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/CSSTokenizer/devel/CSSTokenizer.jflex b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/CSSTokenizer/devel/CSSTokenizer.jflex
new file mode 100644
index 0000000..4648a3f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/CSSTokenizer/devel/CSSTokenizer.jflex
@@ -0,0 +1,522 @@
+/*******************************************************************************

+ * Copyright (c) 2004, 2011 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

+ *******************************************************************************/

+/*nlsXXX*/

+package org.eclipse.wst.css.core.internal.parser;

+

+import java.io.CharArrayReader;

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.List;

+

+import org.eclipse.wst.css.core.internal.parser.regions.CSSTextRegionFactory;

+import org.eclipse.wst.css.core.internal.parserz.CSSRegionContexts;

+import org.eclipse.wst.css.core.internal.parserz.CSSTextToken;

+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;

+

+%%

+

+%public

+%class CSSTokenizer

+%implements CSSRegionContexts, ICSSTokenizer

+%function primGetNextToken

+%type String

+%char

+%unicode

+%caseless

+//%debug

+%pack

+

+%{

+	private final static String UNDEFINED = "undefined";

+	private String fBufferedContext = null;

+	private int fBufferedStart;

+//	private int fBufferedTextLength;

+	private int fBufferedLength;

+//	private StringBuffer fBufferedText = null;

+	private CSSTextRegionFactory fRegionFactory = CSSTextRegionFactory.getInstance();

+	private int fInitialState = YYINITIAL;

+	public final static int BUFFER_SIZE_NORMAL = 16384;

+	public final static int BUFFER_SIZE_SMALL = 256;

+	private int fInitialBufferSize = BUFFER_SIZE_NORMAL;

+

+	public void setInitialState(int state) {

+		fInitialState = state;

+	}

+	

+	public void setInitialBufferSize(int size) {

+		fInitialBufferSize = size;

+	}

+

+	/* user method */

+  	public final ITextRegion getNextToken() throws IOException {

+		String context;

+		String nextTokenType;

+		boolean spaceFollows;

+//		StringBuffer text;

+		int start;

+		int textLength;

+		int length;

+		if (fBufferedContext != null) {

+			context = fBufferedContext;

+//			text = fBufferedText;

+			start = fBufferedStart;

+			textLength = length = fBufferedLength;

+

+			fBufferedContext = null;

+		} else {

+			context = primGetNextToken();

+//			text = new StringBuffer(yytext());

+			start = yychar;

+			textLength = length = yylength();

+		}

+

+		if (context != null) {

+			if (context == UNDEFINED) {

+				// undef -> concatenate undef's

+				nextTokenType = primGetNextToken();

+				while (nextTokenType == UNDEFINED) {

+//					text.append(yytext());

+					textLength += yylength();

+					length = textLength;

+					nextTokenType = primGetNextToken();

+				}

+				fBufferedContext = nextTokenType;

+//				fBufferedText = new StringBuffer(yytext());

+				fBufferedStart = yychar;

+				fBufferedLength = yylength();

+			} else {

+				nextTokenType = null;

+				spaceFollows = false;

+				if (CSSRegionUtil.isDeclarationValueType(context)) { // declaration value can contain VALUE_S

+					nextTokenType = primGetNextToken();

+					spaceFollows = (nextTokenType == CSS_DECLARATION_VALUE_S);

+				} else if (canContainSpace(context)) {

+					nextTokenType = primGetNextToken();

+					spaceFollows = (nextTokenType == CSS_S);

+				}

+				if (nextTokenType != null) { // nextToken is retrieved

+					if (spaceFollows && (context != CSS_COMMENT)) {

+						// next is space -> append

+//						text.append(yytext());

+						length += yylength();

+					} else {

+						// next is NOT space -> push this for next time, return itself

+						fBufferedContext = nextTokenType;

+//						fBufferedText = new StringBuffer(yytext());

+						fBufferedStart = yychar;

+						fBufferedLength = yylength();

+					}

+				}

+			}

+		}

+

+		if (context != null) {

+			if (context == UNDEFINED) {

+				context = CSS_UNKNOWN;

+			}

+			return fRegionFactory.createRegion(context, start, textLength, length);

+		} else {

+			return null;

+		}

+  	}

+

+	/* user method */

+	/* for standalone use */

+  	public final List parseText() throws IOException {

+  		List tokens = new ArrayList();

+

+  		CSSTextToken token;

+		for (String kind = primGetNextToken(); kind != null; kind = primGetNextToken()) {

+			token = new CSSTextToken();

+			token.kind = kind;  				

+			token.start = yychar;

+			token.length = yylength();

+			token.image = yytext();

+			tokens.add(token);

+		}

+

+  		return tokens;

+  	}

+  	

+  	/* user method */

+  	private boolean canContainSpace(String type) {

+  		if (type == CSS_DELIMITER || type == CSS_RBRACE || type == CSS_DECLARATION_DELIMITER) {

+  			return false;

+  		} else {

+  			return true;

+  		}

+  	}

+

+	/* user method */

+	public final int getOffset() {

+		return yychar;

+	}

+	

+	/* user method */

+	public final boolean isEOF() {

+		return zzAtEOF;

+	}

+

+	/* user method */

+	public void reset(char[] charArray) {

+		reset(new CharArrayReader(charArray), 0);

+	}

+

+	/* user method */

+	public final void reset(java.io.Reader in, int newOffset) {

+		/** the input device */

+		zzReader = in;

+

+		/** the current state of the DFA */

+		zzState = 0;

+

+		/** the current lexical state */

+		zzLexicalState = fInitialState; //YYINITIAL;

+

+		/** this buffer contains the current text to be matched and is

+			the source of the yytext() string */

+		if (zzBuffer.length != fInitialBufferSize) {

+			zzBuffer = new char[fInitialBufferSize];

+		}

+		java.util.Arrays.fill(zzBuffer, (char)0);

+

+		/** the textposition at the last accepting state */

+		zzMarkedPos = 0;

+

+		/** the textposition at the last state to be included in yytext */

+//		yy_pushbackPos = 0;

+

+		/** the current text position in the buffer */

+		zzCurrentPos = 0;

+

+		/** startRead marks the beginning of the yytext() string in the buffer */

+		zzStartRead = 0;

+

+		/** endRead marks the last character in the buffer, that has been read

+			from input */

+		zzEndRead = 0;

+

+		/** number of newlines encountered up to the start of the matched text */

+		yyline = 0;

+

+		/** the number of characters up to the start of the matched text */

+		yychar = 0;

+

+		/**

+		 * the number of characters from the last newline up to the start of the 

+		 * matched text

+		 */

+//		yycolumn = 0; 

+

+		/** 

+		 * yy_atBOL == true <=> the scanner is currently at the beginning of a line

+		 */

+//		yy_atBOL = false;

+		

+		/** zzAtEOF == true <=> the scanner has returned a value for EOF */

+		zzAtEOF = false;

+

+		/* user variables */

+		//		fUndefined.delete(0, fUndefined.length());

+	}

+

+	/* user method */

+	public CSSTokenizer() {

+		super();

+	}

+

+	/**

+	 * Added to workaround stricter compilation options without creating

+	 * an alternate skeleton file

+	 */

+	void _usePrivates() {

+		System.out.print(yycolumn);

+		System.out.print(yyline);

+		System.out.print(Boolean.toString(zzAtBOL));

+	}

+%}

+

+%state ST_CHARSET_NAME

+%state ST_CHARSET_DELIMITER

+%state ST_IMPORT_URI

+%state ST_IMPORT_MEDIUM

+%state ST_IMPORT_DELIMITER

+%state ST_MEDIA_MEDIUM

+%state ST_MEDIA_DELIMITER

+%state ST_PAGE_PSEUDO_PAGE

+%state ST_PAGE_DELIMITER

+%state ST_FONT_FACE_DELIMITER

+%state ST_SELECTOR

+%state ST_SELECTOR_MODIFIER

+%state ST_SELECTOR_ATTRIBUTE_NAME

+%state ST_SELECTOR_ATTRIBUTE_OPERATOR

+%state ST_SELECTOR_ATTRIBUTE_VALUE

+%state ST_SELECTOR_ATTRIBUTE_END

+%state ST_DECLARATION

+%state ST_DECLARATION_SEPARATOR

+%state ST_DECLARATION_PRE_VALUE

+%state ST_DECLARATION_VALUE

+

+h = [0-9a-f]

+nonascii = [\u0080-\uffff]

+unicode = \\{h}{1,6}[ \t\r\n\f]?

+escape = {unicode}|\\[ -~\u0080-\uffff]

+

+

+

+nmstart = [_a-zA-Z]|{nonascii}|{escape}

+nmchar = [_a-zA-Z0-9-]|{nonascii}|{escape}

+string1 = \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\"

+string2 = \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\'

+

+ident = -?{nmstart}{nmchar}*

+value_ident = -?{nmstart}"."?({nmchar}+"."?)*

+

+name = {nmchar}+

+num = [+-]?([0-9]+|[0-9]*"."[0-9]+)

+string = {string1}|{string2}

+url = ([ !#$%&*-~]|{nonascii}|{escape})*

+s = [ \t\r\n\f]

+w = {s}*

+nl = \n|\r\n|\r|\f

+

+//range = \?{1,6}|{h}(\?{0,5}|{h}(\?{0,4}|{h}(\?{0,3}|{h}(\?{0,2}|{h}(\??|{h})))))

+

+hash = "#"{name}

+uri = ("url("{w}{string}{w}")"|"url("{w}{url}{w}")")

+function = {ident}"("

+unicode_range = "U"\+[0-9a-fA-F?]{1,6}("-"[0-9a-fA-F?]{1,6})?

+

+%%

+

+/*

+ * *** global ***

+ */

+

+{s}+ { return CSS_S; }

+"<!--" { return CSS_CDO; }

+"-->" { return CSS_CDC; }

+"}" { yybegin(YYINITIAL); return CSS_RBRACE; }

+\/\*[^*]*\*+([^/*][^*]*\*+)*\/ { return CSS_COMMENT; }

+

+//<YYINITIAL> {

+//	"@import" {	yybegin(ST_IMPORT_URI); return CSS_IMPORT; }

+//}

+

+/*

+ * *** charset rule ***

+ * CHARSET_SYM S* STRING S* ';'

+ */

+

+"@charset" { yybegin(ST_CHARSET_NAME); return CSS_CHARSET; }

+

+<ST_CHARSET_NAME> {

+	{string} { yybegin(ST_CHARSET_DELIMITER); return CSS_STRING; }

+}

+

+<ST_CHARSET_DELIMITER> {

+	";" { yybegin(YYINITIAL); return CSS_DELIMITER; }

+}

+

+/*

+ * *** import rule ***

+ * IMPORT_SYM S* [STRING|URI] S* [ medium [ COMMA S* medium]* ]? ';' S*

+ */

+

+"@import" { yybegin(ST_IMPORT_URI); return CSS_IMPORT; }

+

+<ST_IMPORT_URI> {

+	{string} { yybegin(ST_IMPORT_MEDIUM); return CSS_STRING; }

+	//	"url("{w}{string}{w}")" { yybegin(ST_IMPORT_MEDIUM); return CSS_URI; }

+	//	"url("{w}{url}{w}")" { yybegin(ST_IMPORT_MEDIUM); return CSS_URI; }

+	{uri} { yybegin(ST_IMPORT_MEDIUM); return CSS_URI; }

+	";" { yybegin(YYINITIAL); return CSS_DELIMITER; }

+}

+

+<ST_IMPORT_MEDIUM> {

+	{ident} { yybegin(ST_IMPORT_DELIMITER); return CSS_MEDIUM; }

+	";" { yybegin(YYINITIAL); return CSS_DELIMITER; }

+}

+

+<ST_IMPORT_DELIMITER> {

+	";" { yybegin(YYINITIAL); return CSS_DELIMITER; }

+	"," { yybegin(ST_IMPORT_MEDIUM); return CSS_MEDIA_SEPARATOR; }

+}

+

+/*

+ * *** media rule ***

+ * MEDIA_SYM S* medium [ COMMA S* medium ]* LBRACE S* ruleset* '}' S*

+ */

+

+"@media" { yybegin(ST_MEDIA_MEDIUM); return CSS_MEDIA; }

+

+/* 

+ * medium

+ * IDENT S*

+ */

+<ST_MEDIA_MEDIUM> {

+	{ident} { yybegin(ST_MEDIA_DELIMITER); return CSS_MEDIUM; }

+	"{" { yybegin(YYINITIAL); return CSS_LBRACE; }

+}

+

+<ST_MEDIA_DELIMITER> {

+	"{" { yybegin(YYINITIAL); return CSS_LBRACE; }

+	"," { yybegin(ST_MEDIA_MEDIUM); return CSS_MEDIA_SEPARATOR; }

+}

+

+/*

+ * *** page rule **

+ * PAGE_SYM S* pseudo_page? S* LBRACE S* declaration [ ';' S* declaration ]* '}' S*

+ */

+

+"@page" { yybegin(ST_PAGE_PSEUDO_PAGE); return CSS_PAGE; }

+ 

+/*

+ * pseudo_page

+ * ':' IDENT

+ */

+

+<ST_PAGE_PSEUDO_PAGE> {

+	":"?{ident} { yybegin(ST_PAGE_DELIMITER); return CSS_PAGE_SELECTOR; }

+	"{" { yybegin(ST_DECLARATION); return CSS_LBRACE; }

+}

+

+<ST_PAGE_DELIMITER> {

+	"{" { yybegin(ST_DECLARATION); return CSS_LBRACE; }

+}

+

+/*

+ * font-face

+ * FONT_FACE_SYM S* '{' S* declaration [ ';' S* declaration '* '}' S*

+ */

+

+"@font-face" { yybegin(ST_FONT_FACE_DELIMITER); return CSS_FONT_FACE; }

+

+<ST_FONT_FACE_DELIMITER> {

+	"{" { yybegin(ST_DECLARATION); return CSS_LBRACE; }

+}

+

+/*

+ * selector

+ * simple_selector [ combinator simple_selector ]*

+ */

+

+/*

+ * simple_selector

+ * element_name [ HASH | class | attrib | pseudo ]* | [ HASH | class | attrib | pseudo ]+

+ */

+

+<YYINITIAL, ST_SELECTOR_MODIFIER, ST_SELECTOR> {

+	"*" { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_UNIVERSAL; }

+	{hash} { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_ID; }

+//	":"{ident}("("{s}*{ident}{s}*")")? { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_PSEUDO; }

+	":"({ident}("("{s}*([a-zA-Z0-9]|[-+]|{s})*{s}*")")?)? { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_PSEUDO; }

+	"."{name} { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_CLASS; }

+	"[" { yybegin(ST_SELECTOR_ATTRIBUTE_NAME); return CSS_SELECTOR_ATTRIBUTE_START; }

+}

+

+<YYINITIAL, ST_SELECTOR> {

+	{ident} { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_ELEMENT_NAME; }

+}

+

+<ST_SELECTOR_MODIFIER> {

+	"," { yybegin(ST_SELECTOR); return CSS_SELECTOR_SEPARATOR; }

+	// using LOOKAHEAD

+	{s}+/[^+>\{,/] { yybegin(ST_SELECTOR); return CSS_SELECTOR_COMBINATOR; }

+	"+"|">" { yybegin(ST_SELECTOR); return CSS_SELECTOR_COMBINATOR; }

+	"{" { yybegin(ST_DECLARATION); return CSS_LBRACE; }

+}

+

+/*

+ * attrib

+ * '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S* [ IDENT | STRING ] S* ]? ']'

+ */

+

+<ST_SELECTOR_ATTRIBUTE_NAME> {

+	{ident} { yybegin(ST_SELECTOR_ATTRIBUTE_OPERATOR); return CSS_SELECTOR_ATTRIBUTE_NAME; }

+	"]" { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_ATTRIBUTE_END; }

+}

+

+<ST_SELECTOR_ATTRIBUTE_OPERATOR> {

+	"="|"~="|"|="|"*="|"$="|"^=" { yybegin(ST_SELECTOR_ATTRIBUTE_VALUE); return CSS_SELECTOR_ATTRIBUTE_OPERATOR; }

+	"]" { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_ATTRIBUTE_END; }

+}

+

+<ST_SELECTOR_ATTRIBUTE_VALUE> {

+	{ident}|{string} { yybegin(ST_SELECTOR_ATTRIBUTE_END); return CSS_SELECTOR_ATTRIBUTE_VALUE; }

+}

+

+<ST_SELECTOR_ATTRIBUTE_END> {

+	"]" { yybegin(ST_SELECTOR_MODIFIER); return CSS_SELECTOR_ATTRIBUTE_END; }

+}

+

+/*

+ * declaration

+ * property ':' S* expr prio? | // empty //

+ */

+

+<ST_DECLARATION> {

+	\x2A?{ident} { yybegin(ST_DECLARATION_SEPARATOR); return CSS_DECLARATION_PROPERTY; }

+}

+

+<ST_DECLARATION_SEPARATOR> {

+	":" { yybegin(ST_DECLARATION_PRE_VALUE); return CSS_DECLARATION_SEPARATOR; }

+}

+

+<ST_DECLARATION_PRE_VALUE, ST_DECLARATION_VALUE> {

+	"!"{s}*"important" { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_IMPORTANT; }

+	

+	

+	")" { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_PARENTHESIS_CLOSE; }

+	

+	// ordered following two rules deliberately, see 

+	//  https://bugs.eclipse.org/bugs/show_bug.cgi?id=129902

+	{num}{ident} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_DIMENSION; }

+	{value_ident} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_IDENT; }

+

+

+	{num}"%" { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_PERCENTAGE; }

+		

+	{num} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_NUMBER; }

+	

+	

+	

+	{function} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_FUNCTION; }

+	{string} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_STRING; }

+	{uri} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_URI; }

+	"#"{name} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_HASH; }

+	{unicode_range} { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_UNICODE_RANGE; }

+	[,/] { yybegin(ST_DECLARATION_VALUE); return CSS_DECLARATION_VALUE_OPERATOR; }

+}

+

+<ST_DECLARATION_VALUE> {

+	{s}+/[^;}] { return CSS_DECLARATION_VALUE_S; }

+}

+

+<ST_DECLARATION, ST_DECLARATION_SEPARATOR, ST_DECLARATION_PRE_VALUE, ST_DECLARATION_VALUE> {

+	";" { yybegin(ST_DECLARATION); return CSS_DECLARATION_DELIMITER; }

+	//	"}" { yybegin(YYINITIAL); return CSS_RBRACE; }

+}

+

+

+//<YYINITIAL, ST_IMPORT_URI, ST_IMPORT_MEDIUM, ST_IMPORT_DELIMITER> {

+//	\/\*[^*]*\*+([^/*][^*]*\*+)*\/ { return CSS_COMMENT; }

+//	{s}+ { return CSS_S; }

+//	. { return UNDEFINED; }

+//}

+

+//<YYINITIAL, ST_IMPORT_URI, ST_IMPORT_MEDIUM, ST_IMPORT_DELIMITER> {

+//	[^ \t\r\n\f]+ { return CSS_UNKNOWN; }

+//}

+

+. {

+	return UNDEFINED;

+}

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/CSSTokenizer/devel/flex.cmd b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/CSSTokenizer/devel/flex.cmd
new file mode 100644
index 0000000..d39ae78
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/CSSTokenizer/devel/flex.cmd
@@ -0,0 +1,6 @@
+@echo off

+set JAVA_HOME=d:\jdk6_03

+set JFLEX_HOME=D:\JFlex\jflex-1.4.2

+

+%JAVA_HOME%\bin\java -Xmx470M -jar %JFLEX_HOME%\lib\JFlex.jar CSSTokenizer.jflex

+move CSSTokenizer.java ..\..\..\..\..\org.eclipse.wst.css.core\src\org\eclipse\wst\css\core\internal\parser\ && del CSSTokenizer.java*

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/README b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/README
new file mode 100644
index 0000000..3d820e1
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/README
@@ -0,0 +1,9 @@
+devel     - the active development environment (sans JDK)

+            - latest version of HTMLTokenizer specification and generated code

+            - modified skeleton to prevent VM exits on unmatched input

+            - "flex" scripts to run JFlex with modified skeleton

+            - active RCS archive

+resources - backup/pristine resources

+            - Unmodified JFlex 1.2.2 download

+            - Separate modifications to the JFlex skeleton

+            - W3C XML recommendation used for several of the HTMLTokenizer rules

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/JSPTokenizer.java b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/JSPTokenizer.java
new file mode 100644
index 0000000..b424476
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/JSPTokenizer.java
@@ -0,0 +1,3838 @@
+/* The following code was generated by JFlex 1.2.2 on 10/24/07 5:16 AM */
+
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 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.jst.jsp.core.internal.parser.internal;
+
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jst.jsp.core.internal.Logger;
+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockTokenizer;
+import org.eclipse.wst.sse.core.internal.ltk.parser.TagMarker;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.parser.ContextRegionContainer;
+import org.eclipse.wst.xml.core.internal.parser.IntStack;
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.informatik.tu-muenchen.de/~kleing/jflex/">JFlex</a> 1.2.2
+ * on 10/24/07 5:16 AM from the specification file
+ * <tt>file:/D:/eclipse.wtp/workspace/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/JSPTokenizer.jflex</tt>
+ */
+public class JSPTokenizer implements BlockTokenizer, DOMJSPRegionContexts {
+
+  /** this character denotes the end of file */
+  final public static int YYEOF = -1;
+
+  /** lexical states */
+  final public static int ST_JSP_VBL_DQUOTES = 51;
+  final public static int ST_JSP_VBL_SQUOTES = 50;
+  final public static int ST_JSP_VBL_SQUOTES_END = 52;
+  final public static int ST_XML_COMMENT_END = 4;
+  final public static int ST_JSP_DIRECTIVE_ATTRIBUTE_VALUE = 21;
+  final public static int ST_JSP_EL_SQUOTES_END = 45;
+  final public static int ST_JSP_EL_DQUOTES = 44;
+  final public static int ST_JSP_EL = 42;
+  final public static int ST_BLOCK_TAG_SCAN = 36;
+  final public static int ST_JSP_EL_SQUOTES = 43;
+  final public static int ST_DHTML_ATTRIBUTE_VALUE = 14;
+  final public static int ST_XML_PI_ATTRIBUTE_NAME = 8;
+  final public static int ST_DHTML_TAG_CLOSE = 15;
+  final public static int ST_XML_ATTRIBUTE_VALUE_DQUOTED = 41;
+  final public static int ST_DHTML_EQUALS = 13;
+  final public static int ST_XML_PI_ATTRIBUTE_VALUE = 10;
+  final public static int ST_XML_ATTRIBUTE_VALUE = 25;
+  final public static int ST_JSP_VBL = 49;
+  final public static int ST_JSP_SQUOTED_VBL = 55;
+  final public static int ST_XML_ATTRIBUTE_VALUE_SQUOTED = 40;
+  final public static int ST_XML_ATTRIBUTE_NAME = 23;
+  final public static int ST_XML_EQUALS = 24;
+  final public static int YYINITIAL = 0;
+  final public static int ST_JSP_DIRECTIVE_ATTRIBUTE_NAME = 19;
+  final public static int ST_JSP_CONTENT = 16;
+  final public static int ST_XML_DOCTYPE_ID_SYSTEM = 31;
+  final public static int ST_XML_ELEMENT_DECLARATION = 32;
+  final public static int ST_XML_DECLARATION_CLOSE = 27;
+  final public static int ST_JSP_DIRECTIVE_EQUALS = 20;
+  final public static int ST_JSP_VBL_DQUOTES_END = 53;
+  final public static int ST_JSP_DQUOTED_EL = 47;
+  final public static int ST_XML_DOCTYPE_DECLARATION = 28;
+  final public static int ST_CDATA_END = 2;
+  final public static int ST_PI_WS = 6;
+  final public static int ST_CDATA_TEXT = 1;
+  final public static int ST_JSP_DIRECTIVE_NAME_WHITESPACE = 18;
+  final public static int ST_XML_ELEMENT_DECLARATION_CONTENT = 33;
+  final public static int ST_XML_ATTLIST_DECLARATION = 34;
+  final public static int ST_JSP_EL_DQUOTES_END = 46;
+  final public static int ST_JSP_SQUOTED_EL = 48;
+  final public static int ST_JSP_COMMENT_END = 39;
+  final public static int ST_XML_PI_EQUALS = 9;
+  final public static int ST_XML_ATTLIST_DECLARATION_CONTENT = 35;
+  final public static int ST_XML_DOCTYPE_ID_PUBLIC = 30;
+  final public static int ST_JSP_DQUOTED_VBL = 54;
+  final public static int ST_DHTML_ATTRIBUTE_NAME = 12;
+  final public static int ST_ABORT_EMBEDDED = 37;
+  final public static int ST_XML_DOCTYPE_EXTERNAL_ID = 29;
+  final public static int ST_JSP_COMMENT = 38;
+  final public static int ST_PI_CONTENT = 7;
+  final public static int ST_BLOCK_TAG_INTERNAL_SCAN = 37;
+  final public static int ST_PI = 5;
+  final public static int ST_XML_DECLARATION = 26;
+  final public static int ST_JSP_DIRECTIVE_NAME = 17;
+  final public static int ST_XML_TAG_NAME = 22;
+  final public static int ST_XML_PI_TAG_CLOSE = 11;
+  final public static int ST_XML_COMMENT = 3;
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static String yycmap_packed = 
+    "\11\0\1\5\1\26\2\0\1\17\22\0\1\17\1\25\1\12\1\65"+
+    "\1\15\1\22\1\13\1\14\1\24\1\24\1\24\1\24\1\24\1\7"+
+    "\1\6\1\3\12\20\1\11\1\72\1\1\1\51\1\2\1\4\1\21"+
+    "\1\40\1\73\1\36\1\37\1\55\1\70\1\62\1\62\1\63\1\62"+
+    "\1\62\1\33\1\31\1\64\1\52\1\54\1\62\1\67\1\66\1\41"+
+    "\1\71\2\62\1\27\1\53\1\62\1\35\1\104\1\23\1\0\1\10"+
+    "\1\0\1\57\1\103\1\74\1\60\1\43\1\70\1\75\1\106\1\46"+
+    "\1\100\1\62\1\34\1\32\1\50\1\47\1\101\1\62\1\44\1\45"+
+    "\1\56\1\102\1\42\1\62\1\30\1\61\1\62\1\16\1\0\1\105"+
+    "\71\0\1\77\10\0\27\76\1\0\37\76\1\0\72\76\2\0\13\76"+
+    "\2\0\10\76\1\0\65\76\1\0\104\76\11\0\44\76\3\0\2\76"+
+    "\4\0\36\76\70\0\131\76\22\0\7\76\16\0\2\77\56\0\106\77"+
+    "\32\0\2\77\44\0\1\76\1\77\3\76\1\0\1\76\1\0\24\76"+
+    "\1\0\54\76\1\0\7\76\3\0\1\76\1\0\1\76\1\0\1\76"+
+    "\1\0\1\76\1\0\22\76\15\0\14\76\1\0\102\76\1\0\14\76"+
+    "\1\0\44\76\1\0\4\77\11\0\65\76\2\0\2\76\2\0\2\76"+
+    "\3\0\34\76\2\0\10\76\2\0\2\76\67\0\46\76\2\0\1\76"+
+    "\7\0\46\76\12\0\21\77\1\0\27\77\1\0\3\77\1\0\1\77"+
+    "\1\0\2\77\1\0\1\77\13\0\33\76\5\0\3\76\56\0\32\76"+
+    "\5\0\1\77\12\76\10\77\15\0\12\77\6\0\1\77\107\76\2\0"+
+    "\5\76\1\0\17\76\1\0\4\76\1\0\1\76\17\77\2\76\2\77"+
+    "\1\0\4\77\2\0\12\77\u0207\0\3\77\1\0\65\76\2\0\1\77"+
+    "\1\76\20\77\3\0\4\77\3\0\12\76\2\77\2\0\12\77\21\0"+
+    "\3\77\1\0\10\76\2\0\2\76\2\0\26\76\1\0\7\76\1\0"+
+    "\1\76\3\0\4\76\2\0\1\77\1\0\7\77\2\0\2\77\2\0"+
+    "\3\77\11\0\1\77\4\0\2\76\1\0\3\76\2\77\2\0\12\77"+
+    "\2\76\20\0\1\77\2\0\6\76\4\0\2\76\2\0\26\76\1\0"+
+    "\7\76\1\0\2\76\1\0\2\76\1\0\2\76\2\0\1\77\1\0"+
+    "\5\77\4\0\2\77\2\0\3\77\13\0\4\76\1\0\1\76\7\0"+
+    "\12\77\2\77\3\76\14\0\3\77\1\0\7\76\1\0\1\76\1\0"+
+    "\3\76\1\0\26\76\1\0\7\76\1\0\2\76\1\0\5\76\2\0"+
+    "\1\77\1\76\10\77\1\0\3\77\1\0\3\77\22\0\1\76\5\0"+
+    "\12\77\21\0\3\77\1\0\10\76\2\0\2\76\2\0\26\76\1\0"+
+    "\7\76\1\0\2\76\2\0\4\76\2\0\1\77\1\76\6\77\3\0"+
+    "\2\77\2\0\3\77\10\0\2\77\4\0\2\76\1\0\3\76\4\0"+
+    "\12\77\22\0\2\77\1\0\6\76\3\0\3\76\1\0\4\76\3\0"+
+    "\2\76\1\0\1\76\1\0\2\76\3\0\2\76\3\0\3\76\3\0"+
+    "\10\76\1\0\3\76\4\0\5\77\3\0\3\77\1\0\4\77\11\0"+
+    "\1\77\17\0\11\77\21\0\3\77\1\0\10\76\1\0\3\76\1\0"+
+    "\27\76\1\0\12\76\1\0\5\76\4\0\7\77\1\0\3\77\1\0"+
+    "\4\77\7\0\2\77\11\0\2\76\4\0\12\77\22\0\2\77\1\0"+
+    "\10\76\1\0\3\76\1\0\27\76\1\0\12\76\1\0\5\76\4\0"+
+    "\7\77\1\0\3\77\1\0\4\77\7\0\2\77\7\0\1\76\1\0"+
+    "\2\76\4\0\12\77\22\0\2\77\1\0\10\76\1\0\3\76\1\0"+
+    "\27\76\1\0\20\76\4\0\6\77\2\0\3\77\1\0\4\77\11\0"+
+    "\1\77\10\0\2\76\4\0\12\77\221\0\56\76\1\0\1\76\1\77"+
+    "\2\76\7\77\5\0\6\76\1\77\10\77\1\0\12\77\47\0\2\76"+
+    "\1\0\1\76\2\0\2\76\1\0\1\76\2\0\1\76\6\0\4\76"+
+    "\1\0\7\76\1\0\3\76\1\0\1\76\1\0\1\76\2\0\2\76"+
+    "\1\0\2\76\1\0\1\76\1\77\2\76\6\77\1\0\2\77\1\76"+
+    "\2\0\5\76\1\0\1\77\1\0\6\77\2\0\12\77\76\0\2\77"+
+    "\6\0\12\77\13\0\1\77\1\0\1\77\1\0\1\77\4\0\2\77"+
+    "\10\76\1\0\41\76\7\0\24\77\1\0\6\77\4\0\6\77\1\0"+
+    "\1\77\1\0\25\77\3\0\7\77\1\0\1\77\346\0\46\76\12\0"+
+    "\47\76\11\0\1\76\1\0\2\76\1\0\3\76\1\0\1\76\1\0"+
+    "\2\76\1\0\5\76\51\0\1\76\1\0\1\76\1\0\1\76\13\0"+
+    "\1\76\1\0\1\76\1\0\1\76\3\0\2\76\3\0\1\76\5\0"+
+    "\3\76\1\0\1\76\1\0\1\76\1\0\1\76\1\0\1\76\3\0"+
+    "\2\76\3\0\2\76\1\0\1\76\50\0\1\76\11\0\1\76\2\0"+
+    "\1\76\2\0\2\76\7\0\2\76\1\0\1\76\1\0\7\76\50\0"+
+    "\1\76\4\0\1\76\10\0\1\76\u0c06\0\234\76\4\0\132\76\6\0"+
+    "\26\76\2\0\6\76\2\0\46\76\2\0\6\76\2\0\10\76\1\0"+
+    "\1\76\1\0\1\76\1\0\1\76\1\0\37\76\2\0\65\76\1\0"+
+    "\7\76\1\0\1\76\3\0\3\76\1\0\7\76\3\0\4\76\2\0"+
+    "\6\76\4\0\15\76\5\0\3\76\1\0\7\76\323\0\15\77\4\0"+
+    "\1\77\104\0\1\76\3\0\2\76\2\0\1\76\121\0\3\76\u0e82\0"+
+    "\1\77\1\0\1\76\31\0\11\76\6\77\1\0\5\77\13\0\124\76"+
+    "\4\0\2\77\2\0\2\77\2\0\132\76\1\0\3\77\6\0\50\76"+
+    "\u1cd3\0\u51a6\76\u0c5a\0\u2ba4\76\134\0\u0800\0\u1ffe\0\2\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static char [] yycmap = yy_unpack_cmap(yycmap_packed);
+
+  /** 
+   * Translates a state to a row index in the transition table
+   */
+  final private static int yy_rowMap [] = { 
+        0,    71,   142,   213,   284,   355,   426,   497,   568,   639, 
+      710,   781,   852,   923,   994,  1065,  1136,  1207,  1278,  1349, 
+     1420,  1491,  1562,  1633,  1704,  1775,  1846,  1917,  1988,  2059, 
+     2130,  2201,  2272,  2343,  2414,  2485,  2556,  2627,  2698,  2769, 
+     2840,  2911,  2982,  3053,  3124,  3195,  3266,  3337,  3408,  3479, 
+     3550,  3621,  3692,  3763,  3834,  3905,  3976,  4047,  4118,  4189, 
+     4260,  4331,  4402,  4473,  4402,  4473,  4544,  4402,  4402,  4473, 
+     4615,  4686,  4757,  4828,  4899,  4970,  5041,  5112,  4402,  4473, 
+     5183,  5254,  5325,  4402,  5396,  5396,  5467,  5538,  5609,  5183, 
+     4402,  5680,  5751,  4402,  5822,  5893,  5964,  6035,  4402,  4473, 
+     6106,  6177,  6248,  6319,  6390,  6461,  4402,  6532,  6532,  6603, 
+     6674,  6745,  6816,  6887,  4402,  6958,  7029,  7100,  7171,  7242, 
+     7313,  4402,  7384,  7455,  7526,  7597,  7668,  7739,  7810,  7881, 
+     4402,  7952,  8023,  8094,  8165,  8236,  8307,  8378,  8449,  8449, 
+     8520,  8591,  8662,  8733,  8733,  8804,  8875,  8946,  9017,  9017, 
+     9088,  9159,  9230,  9301,  4402,  9372,  9372,  9443,  9514,  9585, 
+     9656,  4402,  4402,  4473,  4402,  4473,  9727,  9798,  9869,  9940, 
+     4402, 10011, 10082, 10153, 10224,  4402, 10295, 10366, 10437, 10508, 
+     4402,  4402, 10579,  4402, 10650, 10721, 10650, 10792, 10863, 10792, 
+     4402,  4402, 10934, 11005, 11076,  4402, 11147, 11218, 11289, 11360, 
+    11431,  4402,  4402, 11502,  4402, 11573, 11644, 11573, 11715, 11786, 
+    11715,  4402,  4402, 11857, 11928, 11999,  4402, 12070, 12141, 12212, 
+     4402,  4402, 12283, 12354, 12425, 12496, 12567,  4402, 12638, 12709, 
+    12780, 12851, 12922, 12993, 13064, 13135,  4402, 13206, 13277, 13348, 
+     4402,  4402,  5396,  5538,  4402, 13419,  5609, 13490,  5680,  5822, 
+     5893, 13561,  5964,  4402, 13632, 13703,  6035, 13774,  4402, 12354, 
+     4402,  6532,  6603,  4402, 13845,  6674, 13916,  4402, 13987, 14058, 
+     7384, 14129,  7597,  4402, 14200,  7668, 14271, 14342, 14413, 14484, 
+    14555, 14626,  8165,  4402, 14697, 14768,  8449,  8520,  4402, 14839, 
+    14910, 14981, 15052, 15123,  8662,  8449,  8733,  8804,  4402,  8875, 
+     8946,  8733,  9017,  9088,  4402, 15194, 15265, 15336, 15407, 15478, 
+    15549, 15620,  9372,  9443,  4402, 15691, 15762, 15833, 15904, 15975, 
+    16046, 16117, 16188, 16259,  4402,  4402,  4402, 16330,  4402,  4402, 
+    16401, 16472, 16543, 16614, 10650,  4402, 16685, 16756, 10792,  4402, 
+    16827, 16898, 16969, 17040, 17111, 17182, 17253, 17324, 17395, 11360, 
+    11573,  4402, 17466, 17537, 11715,  4402, 17608, 17679, 17750, 17821, 
+    17892, 17963, 18034, 18105, 18176,  4402,  4402,  4402, 18247, 18318, 
+    18389, 18460, 18531,  4402, 18602, 18673,  4402,  4402,  4402,  4402, 
+     4402,  4828, 18744, 18815, 18886, 18957, 19028, 19099, 19170, 19099, 
+    19241, 19312, 19241, 19383, 19454, 19525, 19596, 19667, 19738, 19809, 
+    19809, 19880, 19951, 19951, 20022,  9230,  9230,  9230, 20093, 20164, 
+    20235, 20235, 20306,  9585,  9585,  9585, 20377, 20448, 16543, 20519, 
+    10437, 10437, 10437, 20590, 20661, 10650, 10650, 10650, 20732, 20803, 
+    10792, 10792, 10792, 20874, 20945, 10934, 10934, 10934, 17111, 21016, 
+    21087, 11147, 11147, 11147, 17324, 21158, 21229, 11360, 11360, 11360, 
+    21300, 11573, 11573, 11573, 21371, 21442, 11715, 11715, 11715, 21513, 
+    21584, 11857, 11857, 11857, 17892, 21655, 21726, 12070, 12070, 12070, 
+    18105, 21797,  4402,  4402, 21868, 21939,  4402, 22010, 22081, 22152, 
+    22223,  7384,  4402,  4402, 22294, 22365, 22436, 22507, 22578, 15052, 
+    15407,  9230, 22649, 15904,  9585, 22720,  4402, 10437, 10650, 22791, 
+    10792, 22862, 10934, 22933,  4402, 11147, 23004, 11360, 11573, 23075, 
+    11715, 23146, 11857, 23217,  4402, 12070, 23288, 23359, 23430, 23501, 
+    23572, 23643, 23714, 23785, 23856, 23927, 23998, 24069, 24140, 24211, 
+    24282, 24353, 24424, 24495, 24566, 24637, 24708, 24779, 24850,  4828, 
+    24921, 24992, 25063, 25134, 25205,  4402,  4402, 25276, 25347, 25418, 
+    25489, 17111, 17324, 25560, 25631, 17892, 18105, 25702, 25773, 25844, 
+    25915,  4402,  4402,  4402, 25986, 26057, 26128, 26199, 26270, 26341, 
+    26412, 26483,  7100, 26554, 26625, 26696, 26767, 26838, 26909, 26980, 
+     4402, 27051, 27122,  9230,  9585, 10650, 10792, 11573, 11715, 27193, 
+    27264, 27335, 27406, 27477, 27548, 27619, 27690,  4828, 27761, 27832, 
+    27903, 27974, 28045, 28116, 28187, 28258, 28329, 28400, 28471, 28542, 
+    28613, 28684, 28755, 28826, 28897, 28968, 29039, 29110, 29181, 29252, 
+    29323, 29394, 29465, 29536, 29607, 29678, 29749, 29820, 29891, 29962, 
+    30033, 30104, 30175, 30246,  4402, 30317, 30388, 30459, 30530,  7100, 
+    30601, 30672, 30743, 30814, 30885, 30956, 31027, 31098, 31169, 31240, 
+    31311, 31382, 31453, 31524
+  };
+
+  /** 
+   * The packed transition table of the DFA
+   */
+  final private static String yy_packed = 
+    "\1\71\1\72\11\71\1\73\1\71\1\74\4\71\1\75"+
+    "\42\71\1\76\21\71\1\77\1\100\105\77\1\101\1\102"+
+    "\21\101\1\103\2\101\1\104\60\101\1\105\1\106\105\105"+
+    "\1\101\1\102\5\101\1\107\16\101\1\104\61\101\1\102"+
+    "\2\101\1\110\1\111\2\101\2\112\5\101\1\111\6\101"+
+    "\1\111\1\113\1\114\4\112\1\101\10\112\1\115\2\112"+
+    "\1\101\11\112\1\115\1\112\1\101\4\112\1\101\4\112"+
+    "\1\101\4\112\2\101\1\112\1\101\1\102\2\101\1\110"+
+    "\1\116\11\101\1\116\6\101\1\116\60\101\1\117\1\120"+
+    "\2\117\1\121\21\117\1\104\60\117\1\101\1\102\2\101"+
+    "\1\122\1\111\2\101\2\123\5\101\1\111\6\101\1\111"+
+    "\6\123\1\101\13\123\1\101\13\123\1\101\4\123\1\101"+
+    "\4\123\1\101\4\123\2\101\1\123\1\101\1\102\2\101"+
+    "\1\122\1\111\2\101\2\123\5\101\1\111\6\101\1\111"+
+    "\6\123\1\101\13\123\1\124\13\123\1\101\4\123\1\101"+
+    "\4\123\1\101\4\123\2\101\1\123\1\125\1\102\1\101"+
+    "\1\126\1\127\1\111\4\125\1\130\1\125\1\131\2\125"+
+    "\1\111\6\125\1\111\60\125\1\101\1\102\2\101\1\132"+
+    "\21\101\1\104\61\101\1\102\1\133\1\134\1\101\1\111"+
+    "\2\101\2\135\5\101\1\111\6\101\1\111\6\135\1\101"+
+    "\13\135\1\101\13\135\1\101\4\135\1\101\4\135\1\101"+
+    "\4\135\2\101\1\135\1\101\1\102\1\133\1\134\1\101"+
+    "\1\111\2\101\2\135\5\101\1\111\6\101\1\111\6\135"+
+    "\1\101\13\135\1\136\13\135\1\101\4\135\1\101\4\135"+
+    "\1\101\4\135\2\101\1\135\1\137\1\102\1\133\1\140"+
+    "\1\137\1\111\4\137\1\141\1\137\1\142\2\137\1\111"+
+    "\6\137\1\111\60\137\1\101\1\102\3\101\1\111\11\101"+
+    "\1\111\6\101\1\111\60\101\1\143\1\144\20\143\1\145"+
+    "\64\143\1\101\1\146\3\101\1\111\2\101\2\147\5\101"+
+    "\1\111\2\101\1\150\3\101\1\111\6\147\1\101\13\147"+
+    "\1\101\13\147\1\101\4\147\1\101\4\147\1\101\4\147"+
+    "\2\101\1\147\1\101\1\146\3\101\1\151\11\101\1\151"+
+    "\2\101\1\150\3\101\1\151\61\101\1\146\3\101\1\111"+
+    "\2\101\2\152\5\101\1\111\2\101\1\150\3\101\1\111"+
+    "\6\152\1\101\13\152\1\101\13\152\1\101\4\152\1\101"+
+    "\4\152\1\101\4\152\2\101\1\152\1\101\1\146\3\101"+
+    "\1\111\2\101\2\152\5\101\1\111\2\101\1\150\3\101"+
+    "\1\111\6\152\1\101\13\152\1\153\13\152\1\101\4\152"+
+    "\1\101\4\152\1\101\4\152\2\101\1\152\1\154\1\146"+
+    "\1\101\1\155\1\154\1\111\4\154\1\156\1\154\1\157"+
+    "\2\154\1\111\2\154\1\160\3\154\1\111\60\154\1\161"+
+    "\1\162\1\163\1\164\4\161\2\165\15\161\6\166\1\161"+
+    "\13\166\1\161\13\166\1\161\4\166\1\161\4\166\1\161"+
+    "\1\167\3\166\2\161\1\166\1\101\1\170\1\163\1\164"+
+    "\1\101\1\111\2\101\2\171\5\101\1\111\6\101\1\111"+
+    "\6\171\1\101\13\171\1\101\13\171\1\101\4\171\1\101"+
+    "\4\171\1\101\4\171\2\101\1\171\1\101\1\170\1\163"+
+    "\1\164\1\101\1\111\2\101\2\171\5\101\1\111\6\101"+
+    "\1\111\6\171\1\101\13\171\1\172\13\171\1\101\4\171"+
+    "\1\101\4\171\1\101\4\171\2\101\1\171\1\173\1\174"+
+    "\1\163\1\175\1\173\1\111\4\173\1\176\1\173\1\177"+
+    "\1\200\1\173\1\111\6\173\1\111\36\173\1\201\21\173"+
+    "\1\101\1\202\1\203\2\101\1\111\11\101\1\111\6\101"+
+    "\1\111\10\101\1\204\1\205\2\101\1\206\11\101\1\206"+
+    "\1\101\1\205\1\204\27\101\1\102\1\203\2\101\1\111"+
+    "\11\101\1\111\6\101\1\111\6\101\1\207\52\101\1\102"+
+    "\1\203\2\101\1\111\2\101\2\210\5\101\1\111\6\101"+
+    "\1\111\6\210\1\207\13\210\1\101\13\210\1\101\4\210"+
+    "\1\101\4\210\1\101\4\210\2\101\1\210\1\101\1\102"+
+    "\1\203\2\101\1\111\11\101\1\111\6\101\1\111\6\101"+
+    "\1\207\7\101\1\211\6\101\1\212\11\101\1\211\12\101"+
+    "\1\212\5\101\1\213\1\102\1\203\1\214\1\213\1\111"+
+    "\4\213\1\215\1\213\1\216\2\213\1\111\6\213\1\111"+
+    "\6\213\1\217\51\213\1\220\1\102\1\203\1\221\1\220"+
+    "\1\111\4\220\1\222\1\220\1\223\2\220\1\111\6\220"+
+    "\1\111\6\220\1\224\51\220\1\225\1\102\1\203\1\226"+
+    "\1\225\1\111\4\225\1\227\1\225\1\230\2\225\1\111"+
+    "\6\225\1\111\60\225\1\231\1\232\1\233\104\231\1\234"+
+    "\1\102\1\203\1\235\1\234\1\111\4\234\1\236\1\234"+
+    "\1\237\2\234\1\111\6\234\1\111\60\234\1\240\1\241"+
+    "\1\242\104\240\1\243\1\244\105\243\1\101\1\102\24\101"+
+    "\1\104\60\101\1\245\1\246\105\245\1\101\1\102\5\101"+
+    "\1\247\16\101\1\104\60\101\1\250\1\251\3\250\1\252"+
+    "\6\250\1\253\1\254\1\250\1\252\6\250\1\252\36\250"+
+    "\1\255\21\250\1\256\1\251\3\256\1\257\4\256\1\260"+
+    "\2\256\1\261\1\256\1\257\6\256\1\257\36\256\1\262"+
+    "\21\256\1\263\1\264\10\263\1\265\1\263\1\266\1\267"+
+    "\67\263\1\270\1\263\1\271\1\272\12\271\1\101\11\271"+
+    "\1\273\60\271\1\274\1\275\10\274\1\101\13\274\1\276"+
+    "\60\274\1\101\1\102\12\101\1\277\11\101\1\104\61\101"+
+    "\1\102\10\101\1\300\13\101\1\104\60\101\1\301\1\302"+
+    "\10\301\1\260\71\301\1\303\1\304\1\301\1\305\1\306"+
+    "\12\305\1\253\67\305\1\307\1\304\1\305\1\310\1\311"+
+    "\10\310\1\312\1\310\1\313\50\310\1\314\17\310\1\315"+
+    "\1\310\1\316\1\317\12\316\1\101\11\316\1\320\60\316"+
+    "\1\321\1\322\10\321\1\101\13\321\1\323\60\321\1\101"+
+    "\1\102\12\101\1\324\11\101\1\104\61\101\1\102\10\101"+
+    "\1\325\13\101\1\104\60\101\1\326\1\327\10\326\1\260"+
+    "\71\326\1\330\1\331\1\326\1\332\1\333\12\332\1\253"+
+    "\67\332\1\334\1\331\1\332\1\71\1\0\11\71\1\0"+
+    "\1\71\1\0\4\71\1\0\42\71\1\0\21\71\3\0"+
+    "\1\335\1\336\15\0\1\337\2\0\1\340\66\0\1\341"+
+    "\2\0\2\342\5\0\1\341\6\0\1\341\6\342\1\0"+
+    "\13\342\1\0\13\342\1\343\4\342\1\0\4\342\1\0"+
+    "\4\342\2\0\1\342\1\344\1\0\11\344\1\0\1\344"+
+    "\1\345\1\346\3\344\1\0\64\344\5\0\1\341\2\0"+
+    "\2\347\5\0\1\341\6\0\1\341\6\347\1\0\13\347"+
+    "\1\0\13\347\1\0\4\347\1\0\4\347\1\0\4\347"+
+    "\2\0\1\347\1\344\1\0\11\344\1\0\2\344\1\350"+
+    "\3\344\1\0\42\344\1\351\21\344\131\0\1\337\2\0"+
+    "\1\352\104\0\1\353\72\0\1\354\101\0\1\355\111\0"+
+    "\1\111\11\0\1\111\6\0\1\111\66\0\4\112\6\0"+
+    "\1\112\6\0\6\112\1\0\13\112\1\0\13\112\1\0"+
+    "\4\112\1\0\11\112\2\0\1\112\6\0\4\112\6\0"+
+    "\1\112\6\0\2\112\2\356\2\112\1\0\13\112\1\0"+
+    "\13\112\1\0\4\112\1\0\11\112\2\0\1\112\6\0"+
+    "\4\112\6\0\1\112\6\0\2\112\1\356\1\357\2\112"+
+    "\1\0\13\112\1\0\13\112\1\0\4\112\1\0\11\112"+
+    "\2\0\1\112\6\0\4\112\6\0\1\112\6\0\2\112"+
+    "\2\360\2\112\1\0\13\112\1\0\13\112\1\0\4\112"+
+    "\1\0\11\112\2\0\1\112\5\0\1\116\11\0\1\116"+
+    "\6\0\1\116\62\0\1\361\106\0\1\362\112\0\4\123"+
+    "\6\0\1\123\6\0\6\123\1\0\13\123\1\0\13\123"+
+    "\1\0\4\123\1\0\11\123\2\0\1\123\1\125\2\0"+
+    "\1\363\1\125\1\0\4\125\1\0\1\125\1\0\2\125"+
+    "\1\0\6\125\1\0\61\125\1\0\1\362\1\363\1\125"+
+    "\1\0\4\125\1\0\1\125\1\0\2\125\1\0\6\125"+
+    "\1\0\60\125\1\364\1\0\10\364\1\365\2\364\1\366"+
+    "\47\364\1\366\21\364\1\367\1\0\12\367\1\365\1\370"+
+    "\47\367\1\370\21\367\2\0\1\133\1\371\111\0\4\135"+
+    "\6\0\1\135\6\0\6\135\1\0\13\135\1\0\13\135"+
+    "\1\0\4\135\1\0\11\135\2\0\1\135\1\137\2\0"+
+    "\1\372\1\137\1\0\4\137\1\0\1\137\1\0\2\137"+
+    "\1\0\6\137\1\0\61\137\1\0\1\133\1\373\1\137"+
+    "\1\0\4\137\1\0\1\137\1\0\2\137\1\0\6\137"+
+    "\1\0\60\137\1\141\1\0\1\374\1\375\1\141\1\374"+
+    "\4\141\1\376\1\141\1\374\1\377\1\141\1\374\6\141"+
+    "\1\374\36\141\1\377\21\141\1\142\1\0\1\u0100\1\u0101"+
+    "\1\142\1\u0100\4\142\1\u0100\1\142\1\376\1\u0102\1\142"+
+    "\1\u0100\6\142\1\u0100\36\142\1\u0102\21\142\2\0\1\u0103"+
+    "\126\0\1\337\2\0\1\u0104\67\0\4\147\6\0\1\147"+
+    "\6\0\6\147\1\0\13\147\1\0\13\147\1\0\4\147"+
+    "\1\0\11\147\2\0\1\147\2\0\1\u0105\111\0\1\151"+
+    "\11\0\1\151\6\0\1\151\66\0\4\152\6\0\1\152"+
+    "\6\0\6\152\1\0\13\152\1\0\13\152\1\0\4\152"+
+    "\1\0\11\152\2\0\1\152\1\154\2\0\1\u0106\1\154"+
+    "\1\0\4\154\1\0\1\154\1\0\2\154\1\0\6\154"+
+    "\1\0\60\154\1\u0107\1\0\10\u0107\1\u0108\2\u0107\1\u0109"+
+    "\47\u0107\1\u0109\21\u0107\1\u010a\1\0\12\u010a\1\u0108\1\u010b"+
+    "\47\u010a\1\u010b\21\u010a\1\154\1\0\1\u0105\1\u0106\1\154"+
+    "\1\0\4\154\1\0\1\154\1\0\2\154\1\0\6\154"+
+    "\1\0\60\154\1\161\3\0\23\161\6\0\1\161\13\0"+
+    "\1\161\13\0\1\161\4\0\1\161\4\0\1\161\4\0"+
+    "\2\161\4\0\1\335\16\0\1\337\2\0\1\340\63\0"+
+    "\1\u010c\104\0\1\161\3\0\2\161\4\165\6\161\1\165"+
+    "\6\161\6\166\1\161\13\166\1\161\13\166\1\161\4\166"+
+    "\1\161\4\166\1\165\4\166\2\161\1\166\6\0\4\166"+
+    "\6\0\1\166\6\0\6\166\1\0\13\166\1\0\13\166"+
+    "\1\0\4\166\1\0\11\166\2\0\1\166\6\0\4\166"+
+    "\6\0\1\166\6\0\6\166\1\0\7\166\1\u010d\3\166"+
+    "\1\0\13\166\1\0\4\166\1\0\11\166\2\0\1\166"+
+    "\3\0\1\335\4\0\2\u010e\10\0\1\337\2\0\1\340"+
+    "\1\0\6\u010e\1\0\13\u010e\1\0\13\u010e\1\0\4\u010e"+
+    "\1\0\4\u010e\1\0\4\u010e\2\0\1\u010e\6\0\4\171"+
+    "\6\0\1\171\6\0\6\171\1\0\13\171\1\0\13\171"+
+    "\1\0\4\171\1\0\11\171\2\0\1\171\1\173\2\0"+
+    "\1\u010f\1\173\1\0\4\173\1\0\1\173\1\0\2\173"+
+    "\1\0\6\173\1\0\60\173\3\0\1\335\4\0\2\u0110"+
+    "\10\0\1\337\2\0\1\340\1\0\6\u0110\1\0\13\u0110"+
+    "\1\0\13\u0110\1\0\4\u0110\1\0\4\u0110\1\0\4\u0110"+
+    "\2\0\1\u0110\1\173\1\0\1\u010c\1\u010f\1\173\1\0"+
+    "\4\173\1\0\1\173\1\0\2\173\1\0\6\173\1\0"+
+    "\60\173\1\u0111\1\0\10\u0111\1\u0112\2\u0111\1\u0113\47\u0111"+
+    "\1\u0113\21\u0111\1\u0114\1\0\12\u0114\1\u0112\1\u0115\47\u0114"+
+    "\1\u0115\21\u0114\1\173\2\0\1\u010f\1\173\1\0\4\173"+
+    "\1\0\1\173\1\0\1\173\1\u0116\1\0\6\173\1\0"+
+    "\61\173\2\0\1\u010f\1\173\1\0\4\173\1\0\1\173"+
+    "\1\0\1\173\1\u0117\1\0\6\173\1\0\60\173\3\0"+
+    "\1\335\16\0\1\337\2\0\1\u0104\130\0\1\u0118\2\0"+
+    "\1\u0118\75\0\1\u0119\14\0\1\u0119\63\0\2\u011a\52\0"+
+    "\23\u011b\1\u011c\63\u011b\6\0\4\210\6\0\1\210\6\0"+
+    "\6\210\1\0\13\210\1\0\13\210\1\0\4\210\1\0"+
+    "\11\210\2\0\1\210\53\0\1\u011d\5\0\1\u011d\116\0"+
+    "\1\u011e\10\0\1\u011e\4\0\1\213\2\0\1\u011f\1\213"+
+    "\1\0\4\213\1\0\1\213\1\0\2\213\1\0\6\213"+
+    "\1\0\60\213\1\u0120\1\0\10\u0120\1\u0121\2\u0120\1\u0122"+
+    "\47\u0120\1\u0122\21\u0120\1\u0123\1\0\1\u0123\2\u0124\1\u0123"+
+    "\4\u0124\2\u0123\1\u0125\1\u0126\1\u0123\4\u0124\1\u0123\11\u0124"+
+    "\1\u0123\27\u0124\1\u0126\10\u0124\2\u0123\4\u0124\2\u0123\1\u0124"+
+    "\1\217\2\u011b\1\u0127\1\217\1\u011b\4\217\1\u011b\1\217"+
+    "\1\u011b\2\217\1\u011b\3\217\1\u0128\2\217\1\u011b\60\217"+
+    "\1\220\2\0\1\u0129\1\220\1\0\4\220\1\0\1\220"+
+    "\1\0\2\220\1\0\6\220\1\0\60\220\12\u012a\1\u012b"+
+    "\74\u012a\14\u012c\1\u012b\72\u012c\1\224\2\u011b\1\u012d\1\224"+
+    "\1\u011b\4\224\1\u011b\1\224\1\u011b\2\224\1\u011b\3\224"+
+    "\1\u012e\2\224\1\u011b\60\224\1\225\2\0\1\u012f\1\225"+
+    "\1\0\4\225\1\0\1\225\1\0\2\225\1\0\6\225"+
+    "\1\0\60\225\1\u0130\1\0\10\u0130\1\u0131\2\u0130\1\u0132"+
+    "\47\u0130\1\u0132\21\u0130\1\u0133\1\0\1\u0133\2\u0134\1\u0133"+
+    "\4\u0134\2\u0133\1\u0135\1\u0136\1\u0133\4\u0134\1\u0133\11\u0134"+
+    "\1\u0133\27\u0134\1\u0136\10\u0134\2\u0133\4\u0134\2\u0133\1\u0134"+
+    "\2\231\1\0\106\231\1\0\17\231\1\u0137\2\231\1\u0138"+
+    "\61\231\1\234\2\0\1\u0139\1\234\1\0\4\234\1\0"+
+    "\1\234\1\0\2\234\1\0\6\234\1\0\60\234\1\u013a"+
+    "\1\0\10\u013a\1\u013b\2\u013a\1\u013c\47\u013a\1\u013c\21\u013a"+
+    "\1\u013d\1\0\1\u013d\2\u013e\1\u013d\4\u013e\2\u013d\1\u013f"+
+    "\1\u0140\1\u013d\4\u013e\1\u013d\11\u013e\1\u013d\27\u013e\1\u0140"+
+    "\10\u013e\2\u013d\4\u013e\2\u013d\1\u013e\2\240\1\0\106\240"+
+    "\1\0\17\240\1\u0141\2\240\1\u0142\61\240\7\0\1\u0143"+
+    "\77\0\1\250\1\0\12\250\1\0\1\u0144\47\250\1\u0144"+
+    "\21\250\3\0\1\u0145\16\0\1\337\2\0\1\352\61\0"+
+    "\1\250\1\0\3\250\1\252\6\250\1\0\1\u0144\1\250"+
+    "\1\252\6\250\1\252\36\250\1\u0144\37\250\1\u0146\106\250"+
+    "\1\u0147\70\250\1\256\1\0\10\256\1\0\2\256\1\u0148"+
+    "\47\256\1\u0148\22\256\1\0\3\256\1\257\4\256\1\0"+
+    "\2\256\1\u0148\1\256\1\257\6\256\1\257\36\256\1\u0148"+
+    "\37\256\1\u0149\106\256\1\u014a\70\256\12\263\1\0\1\263"+
+    "\1\0\1\u014b\67\263\1\0\13\263\1\0\1\263\1\0"+
+    "\1\u014b\4\263\1\u014c\62\263\1\0\13\263\1\0\1\263"+
+    "\1\0\1\263\1\u014d\66\263\1\u014e\1\263\14\u014f\1\u0150"+
+    "\106\u014f\1\u0150\5\u014f\1\u0151\2\u014f\1\u0152\61\u014f\12\u0153"+
+    "\1\u0154\106\u0153\1\u0154\7\u0153\1\u0155\2\u0153\1\u0156\61\u0153"+
+    "\12\301\1\0\71\301\1\u0157\1\0\13\301\1\0\7\301"+
+    "\1\u0158\61\301\1\u0157\1\0\13\301\1\u0159\74\301\14\305"+
+    "\1\0\67\305\1\u015a\1\0\15\305\1\0\5\305\1\u015b"+
+    "\61\305\1\u015a\1\0\15\305\1\u015c\72\305\12\310\1\0"+
+    "\1\310\1\0\70\310\1\0\13\310\1\0\1\310\1\0"+
+    "\5\310\1\u015d\62\310\1\0\13\310\1\0\1\310\1\0"+
+    "\1\310\1\u015e\66\310\1\0\1\310\14\u015f\1\u0160\106\u015f"+
+    "\1\u0160\5\u015f\1\u0161\2\u015f\1\u0162\61\u015f\12\u0163\1\u0164"+
+    "\106\u0163\1\u0164\7\u0163\1\u0165\2\u0163\1\u0166\61\u0163\12\326"+
+    "\1\0\71\326\1\u0167\1\0\13\326\1\0\7\326\1\u0168"+
+    "\61\326\1\u0167\1\0\13\326\1\u0169\74\326\14\332\1\0"+
+    "\67\332\1\u016a\1\0\15\332\1\0\5\332\1\u016b\61\332"+
+    "\1\u016a\1\0\15\332\1\u016c\72\332\7\0\1\u016d\11\0"+
+    "\1\u016e\3\0\1\u016f\23\0\1\u0170\44\0\1\u0171\25\0"+
+    "\1\u0172\56\0\1\341\2\0\2\u0173\5\0\1\341\6\0"+
+    "\1\341\6\u0173\1\0\13\u0173\1\0\13\u0173\1\0\4\u0173"+
+    "\1\0\4\u0173\1\0\4\u0173\2\0\1\u0173\1\u0174\1\0"+
+    "\3\u0174\1\u0175\4\342\1\u0174\1\0\3\u0174\1\u0175\1\342"+
+    "\1\u0174\1\0\3\u0174\1\u0175\6\342\1\u0174\13\342\1\u0174"+
+    "\13\342\1\u0174\4\342\1\u0176\11\342\2\u0174\1\342\20\0"+
+    "\1\u0177\7\0\1\u0178\73\0\1\345\71\0\105\346\1\u0179"+
+    "\1\346\1\u0174\1\0\3\u0174\1\u0175\4\347\1\u0174\1\0"+
+    "\3\u0174\1\u0175\1\347\1\u0174\1\0\3\u0174\1\u0175\6\347"+
+    "\1\u0174\13\347\1\u0174\13\347\1\u0174\4\347\1\u017a\11\347"+
+    "\2\u0174\1\347\105\350\1\u017b\1\350\65\0\1\351\56\0"+
+    "\1\u0172\53\0\1\u017c\106\0\1\u017d\112\0\4\112\6\0"+
+    "\1\112\6\0\4\112\2\u017e\1\0\13\112\1\0\13\112"+
+    "\1\0\4\112\1\0\11\112\2\0\1\112\6\0\4\112"+
+    "\6\0\1\112\6\0\4\112\1\u017e\1\u017f\1\0\13\112"+
+    "\1\0\13\112\1\0\4\112\1\0\11\112\2\0\1\112"+
+    "\6\0\4\112\6\0\1\112\6\0\6\112\1\0\13\112"+
+    "\1\0\2\112\1\u0180\10\112\1\0\4\112\1\0\6\112"+
+    "\1\u0180\2\112\2\0\1\112\12\364\1\365\3\364\1\0"+
+    "\70\364\14\367\1\365\1\367\1\0\70\367\1\374\1\0"+
+    "\10\374\1\376\2\374\1\u0181\47\374\1\u0181\21\374\1\141"+
+    "\2\374\1\375\1\141\1\374\4\141\1\376\1\141\1\374"+
+    "\1\141\1\137\1\374\6\141\1\374\60\141\1\u0100\1\0"+
+    "\12\u0100\1\376\1\u0182\47\u0100\1\u0182\21\u0100\1\142\2\u0100"+
+    "\1\u0101\1\142\1\u0100\4\142\1\u0100\1\142\1\376\1\142"+
+    "\1\137\1\u0100\6\142\1\u0100\60\142\12\u0107\1\u0108\3\u0107"+
+    "\1\0\70\u0107\14\u010a\1\u0108\1\u010a\1\0\70\u010a\6\0"+
+    "\4\166\6\0\1\166\6\0\6\166\1\0\13\166\1\0"+
+    "\13\166\1\0\4\166\1\0\6\166\1\u0183\2\166\2\0"+
+    "\1\166\6\0\4\u010e\6\0\1\u010e\6\0\6\u010e\1\0"+
+    "\13\u010e\1\0\13\u010e\1\0\4\u010e\1\0\11\u010e\2\0"+
+    "\1\u010e\6\0\4\u0110\6\0\1\u0110\6\0\6\u0110\1\0"+
+    "\13\u0110\1\0\13\u0110\1\0\4\u0110\1\0\11\u0110\2\0"+
+    "\1\u0110\12\u0111\1\u0112\3\u0111\1\0\70\u0111\14\u0114\1\u0112"+
+    "\1\u0114\1\0\70\u0114\1\u0184\2\u0185\1\u0186\1\u0184\1\u0185"+
+    "\4\u0184\1\u0185\1\u0184\1\u0185\2\u0184\1\u0185\6\u0184\1\u0185"+
+    "\56\u0184\1\173\1\u0184\1\u0187\2\u0188\1\u0189\1\u0187\1\u0188"+
+    "\4\u0187\1\u0188\1\u0187\1\u0188\2\u0187\1\u0188\6\u0187\1\u0188"+
+    "\56\u0187\1\173\1\u0187\36\0\1\u018a\35\0\1\u018a\53\0"+
+    "\1\u018b\14\0\1\u018b\73\0\1\u018c\11\0\1\u018c\76\0"+
+    "\1\u018d\20\0\1\u018d\113\0\1\u018e\7\0\1\u018e\3\0"+
+    "\12\u0120\1\u0121\3\u0120\1\0\70\u0120\1\u0123\1\0\12\u0123"+
+    "\1\u0121\1\u018f\47\u0123\1\u018f\22\u0123\1\0\12\u0123\1\u0190"+
+    "\1\u018f\47\u0123\1\u018f\21\u0123\14\0\1\u0191\72\0\14\u0123"+
+    "\1\u0190\1\u0123\1\0\70\u0123\12\u0130\1\u0131\3\u0130\1\0"+
+    "\70\u0130\1\u0133\1\0\12\u0133\1\u0131\1\u0192\47\u0133\1\u0192"+
+    "\22\u0133\1\0\12\u0133\1\u0193\1\u0192\47\u0133\1\u0192\21\u0133"+
+    "\14\0\1\u0194\72\0\14\u0133\1\u0193\1\u0133\1\0\70\u0133"+
+    "\2\231\1\0\4\231\1\u0195\11\231\1\u0196\3\231\1\u0197"+
+    "\23\231\1\u0198\37\231\1\0\32\231\1\u0199\51\231\12\u013a"+
+    "\1\u013b\3\u013a\1\0\70\u013a\1\u013d\1\0\12\u013d\1\u013b"+
+    "\1\u019a\47\u013d\1\u019a\22\u013d\1\0\12\u013d\1\u019b\1\u019a"+
+    "\47\u013d\1\u019a\21\u013d\14\0\1\u019c\72\0\14\u013d\1\u019b"+
+    "\1\u013d\1\0\70\u013d\2\240\1\0\4\240\1\u019d\11\240"+
+    "\1\u019e\3\240\1\u019f\23\240\1\u01a0\37\240\1\0\32\240"+
+    "\1\u01a1\51\240\22\0\1\u01a2\64\0\16\250\1\0\70\250"+
+    "\16\256\1\0\70\256\12\263\1\0\1\263\1\0\1\263"+
+    "\1\u01a3\66\263\1\u014e\10\263\1\u01a4\2\263\1\0\1\263"+
+    "\1\0\1\u014b\3\263\1\u01a5\3\263\1\u01a6\23\263\1\u01a7"+
+    "\33\263\1\0\1\263\12\u01a3\1\0\1\u01a3\1\0\70\u01a3"+
+    "\1\0\1\u01a3\12\u014e\1\0\1\u014e\1\0\1\u01a8\67\u014e"+
+    "\1\0\1\u014e\7\u014f\1\u01a9\4\u014f\1\u0150\4\u014f\1\u01aa"+
+    "\3\u014f\1\u01ab\23\u014f\1\u01ac\51\u014f\1\u0150\20\u014f\1\u01ad"+
+    "\51\u014f\7\u0153\1\u01ae\2\u0153\1\u0154\6\u0153\1\u01af\3\u0153"+
+    "\1\u01b0\23\u0153\1\u01b1\47\u0153\1\u0154\22\u0153\1\u01b2\51\u0153"+
+    "\12\301\1\0\103\301\1\u01b3\2\301\1\0\6\301\1\u01b4"+
+    "\3\301\1\u01b5\23\301\1\u01b6\32\301\1\u0157\1\0\1\301"+
+    "\104\u01b7\1\u01b8\2\u01b7\14\305\1\0\101\305\1\u01b9\4\305"+
+    "\1\0\4\305\1\u01ba\3\305\1\u01bb\23\305\1\u01bc\32\305"+
+    "\1\u015a\1\0\1\305\104\u01bd\1\u01be\2\u01bd\7\310\1\u01bf"+
+    "\2\310\1\0\1\310\1\0\4\310\1\u01c0\3\310\1\u01c1"+
+    "\23\310\1\u01c2\33\310\1\0\1\310\7\u015f\1\u01c3\4\u015f"+
+    "\1\u0160\4\u015f\1\u01c4\3\u015f\1\u01c5\23\u015f\1\u01c6\51\u015f"+
+    "\1\u0160\20\u015f\1\u01c7\51\u015f\7\u0163\1\u01c8\2\u0163\1\u0164"+
+    "\6\u0163\1\u01c9\3\u0163\1\u01ca\23\u0163\1\u01cb\47\u0163\1\u0164"+
+    "\22\u0163\1\u01cc\51\u0163\12\326\1\0\103\326\1\u01cd\2\326"+
+    "\1\0\6\326\1\u01ce\3\326\1\u01cf\23\326\1\u01d0\32\326"+
+    "\1\u0167\1\0\1\326\104\u01d1\1\u01d2\2\u01d1\14\332\1\0"+
+    "\101\332\1\u01d3\4\332\1\0\4\332\1\u01d4\3\332\1\u01d5"+
+    "\23\332\1\u01d6\32\332\1\u016a\1\0\1\332\104\u01d7\1\u01d8"+
+    "\2\u01d7\7\0\1\u01d9\106\0\1\u01da\135\0\1\u01db\50\0"+
+    "\1\u0173\1\0\11\u0173\1\0\6\u0173\1\0\64\u0173\1\u0174"+
+    "\1\0\11\u0174\1\0\6\u0174\1\0\47\u0174\1\0\15\u0174"+
+    "\1\0\3\u0174\1\u0175\5\u0174\1\0\3\u0174\1\u0175\2\u0174"+
+    "\1\0\3\u0174\1\u0175\43\u0174\1\u01dc\14\u0174\20\0\1\u0177"+
+    "\51\0\1\u01dd\34\0\1\u01de\15\0\3\u01de\2\0\1\u01de"+
+    "\11\0\1\u01de\1\0\2\u01de\7\0\1\u01de\2\0\2\u01de"+
+    "\6\0\1\u01de\11\0\1\112\1\u01df\2\112\6\0\1\112"+
+    "\6\0\6\112\1\0\13\112\1\0\13\112\1\0\4\112"+
+    "\1\0\11\112\2\0\1\112\6\0\4\112\6\0\1\112"+
+    "\6\0\6\112\1\0\11\112\1\u01e0\1\112\1\0\1\u01e0"+
+    "\12\112\1\0\4\112\1\0\11\112\2\0\1\112\12\374"+
+    "\1\376\3\374\1\0\70\374\14\u0100\1\376\1\u0100\1\0"+
+    "\70\u0100\6\0\3\166\1\u01e1\6\0\1\166\6\0\6\166"+
+    "\1\0\13\166\1\0\13\166\1\0\4\166\1\0\11\166"+
+    "\2\0\1\166\1\u0184\2\u0185\1\u0186\1\u0184\1\u0185\4\u0184"+
+    "\1\u0185\1\u0184\1\u0185\2\u0184\1\u0185\6\u0184\1\u0185\56\u0184"+
+    "\1\u01e2\1\u0184\105\u0185\1\u01e3\1\u0185\1\u0187\2\u0188\1\u0189"+
+    "\1\u0187\1\u0188\4\u0187\1\u0188\1\u0187\1\u0188\2\u0187\1\u0188"+
+    "\6\u0187\1\u0188\56\u0187\1\u01e2\1\u0187\105\u0188\1\u01e4\1\u0188"+
+    "\41\0\1\u01e5\14\0\1\u01e5\63\0\2\u01e6\103\0\2\u01e7"+
+    "\115\0\1\u01e8\14\0\1\u01e8\63\0\2\u01e9\52\0\14\u0123"+
+    "\1\u0121\1\u0123\1\0\70\u0123\3\0\2\u01ea\1\0\4\u01ea"+
+    "\2\0\1\u0125\1\u01ea\1\0\4\u01ea\1\0\11\u01ea\1\0"+
+    "\40\u01ea\2\0\4\u01ea\2\0\1\u01ea\14\u0133\1\u0131\1\u0133"+
+    "\1\0\70\u0133\3\0\2\u01eb\1\0\4\u01eb\2\0\1\u0135"+
+    "\1\u01eb\1\0\4\u01eb\1\0\11\u01eb\1\0\40\u01eb\2\0"+
+    "\4\u01eb\2\0\1\u01eb\2\231\1\0\4\231\1\u01ec\101\231"+
+    "\1\0\33\231\1\u01ed\50\231\14\u013d\1\u013b\1\u013d\1\0"+
+    "\70\u013d\3\0\2\u01ee\1\0\4\u01ee\2\0\1\u013f\1\u01ee"+
+    "\1\0\4\u01ee\1\0\11\u01ee\1\0\40\u01ee\2\0\4\u01ee"+
+    "\2\0\1\u01ee\2\240\1\0\4\240\1\u01ef\101\240\1\0"+
+    "\33\240\1\u01f0\50\240\2\0\1\u01f1\104\0\7\263\1\u01f2"+
+    "\2\263\1\0\1\263\1\0\1\u014b\67\263\1\0\1\263"+
+    "\12\u014e\1\0\1\u014e\1\0\1\u014e\1\0\70\u014e\7\u014f"+
+    "\1\u01f3\4\u014f\1\u0150\106\u014f\1\u0150\21\u014f\1\u01f4\50\u014f"+
+    "\7\u0153\1\u01f5\2\u0153\1\u0154\106\u0153\1\u0154\23\u0153\1\u01f6"+
+    "\50\u0153\7\301\1\u01f7\2\301\1\0\71\301\1\u0157\1\0"+
+    "\1\301\12\u01f8\1\u01f9\72\u01f8\1\0\1\u01f8\7\305\1\u01fa"+
+    "\4\305\1\0\67\305\1\u015a\1\0\1\305\14\u01fb\1\u01f9"+
+    "\70\u01fb\1\0\1\u01fb\7\310\1\u01fc\2\310\1\0\1\310"+
+    "\1\0\70\310\1\0\1\310\7\u015f\1\u01fd\4\u015f\1\u0160"+
+    "\106\u015f\1\u0160\21\u015f\1\u01fe\50\u015f\7\u0163\1\u01ff\2\u0163"+
+    "\1\u0164\106\u0163\1\u0164\23\u0163\1\u0200\50\u0163\7\326\1\u0201"+
+    "\2\326\1\0\71\326\1\u0167\1\0\1\326\12\u0202\1\u0203"+
+    "\72\u0202\1\0\1\u0202\7\332\1\u0204\4\332\1\0\67\332"+
+    "\1\u016a\1\0\1\332\14\u0205\1\u0203\70\u0205\1\0\1\u0205"+
+    "\37\0\1\u0206\141\0\1\u01dc\34\0\1\u01de\15\0\3\u01de"+
+    "\2\0\1\u01de\11\0\1\u01de\1\0\2\u01de\7\0\1\u01de"+
+    "\1\0\1\u01dd\2\u01de\6\0\1\u01de\11\0\4\112\6\0"+
+    "\1\112\6\0\6\112\1\0\7\112\1\u0207\3\112\1\0"+
+    "\13\112\1\0\4\112\1\0\11\112\2\0\1\112\6\0"+
+    "\4\112\6\0\1\112\6\0\6\112\1\0\6\112\1\u0208"+
+    "\4\112\1\0\13\112\1\0\1\112\1\u0208\2\112\1\0"+
+    "\11\112\2\0\1\112\6\0\4\166\6\0\1\166\6\0"+
+    "\6\166\1\0\6\166\1\u0209\4\166\1\0\6\166\1\u020a"+
+    "\4\166\1\0\4\166\1\0\11\166\2\0\1\166\53\0"+
+    "\1\u020b\5\0\1\u020b\73\0\1\u020c\14\0\1\u020c\66\0"+
+    "\1\u020d\11\0\1\u020d\74\0\1\u020e\11\0\1\u020e\77\0"+
+    "\1\u020f\14\0\1\u020f\23\0\2\231\1\0\34\231\1\u0210"+
+    "\47\231\2\240\1\0\34\240\1\u0211\47\240\14\u014f\1\u0150"+
+    "\22\u014f\1\u0212\47\u014f\12\u0153\1\u0154\24\u0153\1\u0213\47\u0153"+
+    "\12\u01f8\1\u01b7\71\u01f8\1\u0214\1\u01b7\1\u01f8\14\u01fb\1\u01bd"+
+    "\67\u01fb\1\u0215\1\u01bd\1\u01fb\14\u015f\1\u0160\22\u015f\1\u0216"+
+    "\47\u015f\12\u0163\1\u0164\24\u0163\1\u0217\47\u0163\12\u0202\1\u01d1"+
+    "\71\u0202\1\u0218\1\u01d1\1\u0202\14\u0205\1\u01d7\67\u0205\1\u0219"+
+    "\1\u01d7\1\u0205\40\0\1\u021a\54\0\4\112\6\0\1\112"+
+    "\6\0\6\112\1\0\13\112\1\0\4\112\1\u021b\6\112"+
+    "\1\0\4\112\1\0\11\112\2\0\1\112\6\0\4\112"+
+    "\6\0\1\112\6\0\6\112\1\0\3\112\1\u021c\7\112"+
+    "\1\0\4\112\1\u021c\6\112\1\0\4\112\1\0\11\112"+
+    "\2\0\1\112\6\0\4\166\6\0\1\166\6\0\6\166"+
+    "\1\0\11\166\1\u021d\1\166\1\0\13\166\1\0\4\166"+
+    "\1\0\11\166\2\0\1\166\6\0\4\166\6\0\1\166"+
+    "\6\0\6\166\1\0\10\166\1\u021e\2\166\1\0\13\166"+
+    "\1\0\4\166\1\0\11\166\2\0\1\166\54\0\1\u021f"+
+    "\24\0\1\u021f\52\0\1\u0220\20\0\1\u0220\70\0\1\u0221"+
+    "\13\0\1\u0221\53\0\2\u0222\112\0\1\u0223\35\0\1\u0223"+
+    "\12\0\2\231\1\0\35\231\1\u0224\46\231\2\240\1\0"+
+    "\35\240\1\u0225\46\240\14\u014f\1\u0150\23\u014f\1\u0226\46\u014f"+
+    "\12\u0153\1\u0154\25\u0153\1\u0227\46\u0153\12\u01f8\1\u0228\71\u01f8"+
+    "\1\u0214\1\u01b7\1\u01f8\14\u01fb\1\u0229\67\u01fb\1\u0215\1\u01bd"+
+    "\1\u01fb\14\u015f\1\u0160\23\u015f\1\u022a\46\u015f\12\u0163\1\u0164"+
+    "\25\u0163\1\u022b\46\u0163\12\u0202\1\u022c\71\u0202\1\u0218\1\u01d1"+
+    "\1\u0202\14\u0205\1\u022d\67\u0205\1\u0219\1\u01d7\1\u0205\41\0"+
+    "\1\u022e\53\0\4\112\6\0\1\112\6\0\6\112\1\0"+
+    "\13\112\1\0\7\112\1\u022f\3\112\1\0\4\112\1\0"+
+    "\11\112\2\0\1\112\6\0\4\166\6\0\1\166\6\0"+
+    "\6\166\1\0\11\166\1\u0230\1\166\1\0\13\166\1\0"+
+    "\4\166\1\0\11\166\2\0\1\166\6\0\4\166\6\0"+
+    "\1\166\6\0\6\166\1\0\6\166\1\u0231\4\166\1\0"+
+    "\13\166\1\0\4\166\1\0\11\166\2\0\1\166\43\0"+
+    "\1\u0232\11\0\1\u0232\72\0\1\u0233\14\0\1\u0233\71\0"+
+    "\1\u0234\14\0\1\u0234\30\0\2\231\1\0\36\231\1\u0235"+
+    "\45\231\2\240\1\0\36\240\1\u0236\45\240\14\u014f\1\u0150"+
+    "\24\u014f\1\u0237\45\u014f\12\u0153\1\u0154\26\u0153\1\u0238\45\u0153"+
+    "\14\u015f\1\u0160\24\u015f\1\u0239\45\u015f\12\u0163\1\u0164\26\u0163"+
+    "\1\u023a\45\u0163\40\0\1\u023b\54\0\4\112\6\0\1\112"+
+    "\6\0\5\112\1\u023c\1\0\13\112\1\0\13\112\1\0"+
+    "\4\112\1\0\11\112\2\0\1\112\6\0\4\166\6\0"+
+    "\1\166\6\0\6\166\1\0\13\166\1\0\4\166\1\u023d"+
+    "\6\166\1\0\4\166\1\0\11\166\2\0\1\166\6\0"+
+    "\4\166\6\0\1\166\6\0\6\166\1\0\5\166\1\u023e"+
+    "\5\166\1\0\13\166\1\0\4\166\1\0\11\166\2\0"+
+    "\1\166\2\231\1\0\35\231\1\u023f\46\231\2\240\1\0"+
+    "\35\240\1\u0240\46\240\14\u014f\1\u0150\23\u014f\1\u0241\46\u014f"+
+    "\12\u0153\1\u0154\25\u0153\1\u0242\46\u0153\14\u015f\1\u0160\23\u015f"+
+    "\1\u0243\46\u015f\12\u0163\1\u0164\25\u0163\1\u0244\46\u0163\35\0"+
+    "\1\u0245\57\0\4\112\6\0\1\112\6\0\6\112\1\0"+
+    "\5\112\1\u0246\5\112\1\0\13\112\1\0\4\112\1\0"+
+    "\11\112\2\0\1\112\6\0\4\166\6\0\1\166\6\0"+
+    "\6\166\1\0\13\166\1\0\13\166\1\0\4\166\1\0"+
+    "\1\166\1\u0247\7\166\2\0\1\166\2\231\1\0\32\231"+
+    "\1\u0248\51\231\2\240\1\0\32\240\1\u0249\51\240\14\u014f"+
+    "\1\u0150\20\u014f\1\u024a\51\u014f\12\u0153\1\u0154\22\u0153\1\u024b"+
+    "\51\u0153\14\u015f\1\u0160\20\u015f\1\u024c\51\u015f\12\u0163\1\u0164"+
+    "\22\u0163\1\u024d\51\u0163\6\0\4\112\6\0\1\112\6\0"+
+    "\6\112\1\0\7\112\1\u024e\3\112\1\0\13\112\1\0"+
+    "\4\112\1\0\11\112\2\0\1\112\6\0\4\166\6\0"+
+    "\1\166\6\0\6\166\1\0\13\166\1\0\4\166\1\u024f"+
+    "\6\166\1\0\4\166\1\0\11\166\2\0\1\166\6\0"+
+    "\4\112\6\0\1\112\6\0\6\112\1\0\13\112\1\0"+
+    "\13\112\1\0\4\112\1\0\11\112\2\0\1\u0250\6\0"+
+    "\4\166\6\0\1\166\6\0\6\166\1\0\10\166\1\u0251"+
+    "\2\166\1\0\13\166\1\0\4\166\1\0\11\166\2\0"+
+    "\1\166\6\0\4\112\6\0\1\112\6\0\6\112\1\0"+
+    "\5\112\1\u0252\5\112\1\0\13\112\1\0\4\112\1\0"+
+    "\11\112\2\0\1\112\6\0\4\166\6\0\1\166\6\0"+
+    "\6\166\1\0\4\166\1\u0253\6\166\1\0\13\166\1\0"+
+    "\4\166\1\0\11\166\2\0\1\166\6\0\4\112\6\0"+
+    "\1\112\6\0\6\112\1\0\5\112\1\u0254\5\112\1\0"+
+    "\13\112\1\0\4\112\1\0\11\112\2\0\1\112\6\0"+
+    "\4\166\6\0\1\166\6\0\6\166\1\0\5\166\1\u0255"+
+    "\5\166\1\0\13\166\1\0\4\166\1\0\11\166\2\0"+
+    "\1\166\6\0\4\112\6\0\1\112\6\0\6\112\1\0"+
+    "\13\112\1\0\4\112\1\u0256\6\112\1\0\4\112\1\0"+
+    "\11\112\2\0\1\112\6\u0257\4\u0258\6\u0257\1\u0258\5\u0257"+
+    "\1\0\6\u0258\1\u0257\13\u0258\1\u0257\13\u0258\1\u0257\4\u0258"+
+    "\1\u0257\11\u0258\2\u0257\1\u0258\42\0\1\u0259\3\0\1\u025a"+
+    "\7\0\1\u025b\1\u025c\21\0\1\u025d\13\0\4\166\6\0"+
+    "\1\166\6\0\6\166\1\0\4\166\1\u025e\3\166\1\u025f"+
+    "\2\166\1\0\4\166\1\u0260\1\u0261\5\166\1\0\4\166"+
+    "\1\0\6\166\1\u0262\2\166\2\0\1\166\57\0\1\u0263"+
+    "\77\0\1\u0264\115\0\1\u0265\105\0\1\u0266\107\0\1\u0267"+
+    "\35\0\4\166\6\0\1\166\6\0\6\166\1\0\13\166"+
+    "\1\0\5\166\1\u0268\5\166\1\0\4\166\1\0\11\166"+
+    "\2\0\1\166\6\0\4\166\6\0\1\166\6\0\6\166"+
+    "\1\0\12\166\1\u0269\1\0\13\166\1\0\4\166\1\0"+
+    "\11\166\2\0\1\166\6\0\4\166\6\0\1\166\6\0"+
+    "\6\166\1\0\13\166\1\0\5\166\1\u026a\5\166\1\0"+
+    "\4\166\1\0\11\166\2\0\1\166\6\0\4\166\6\0"+
+    "\1\166\6\0\6\166\1\0\13\166\1\0\4\166\1\u026b"+
+    "\6\166\1\0\4\166\1\0\11\166\2\0\1\166\6\0"+
+    "\4\166\6\0\1\166\6\0\6\166\1\0\13\166\1\0"+
+    "\5\166\1\u026c\5\166\1\0\4\166\1\0\11\166\2\0"+
+    "\1\166\44\0\1\u026d\136\0\1\u026e\107\0\1\u026f\67\0"+
+    "\1\u0270\125\0\1\u0271\17\0\4\166\6\0\1\166\6\0"+
+    "\6\166\1\0\6\166\1\u0272\4\166\1\0\13\166\1\0"+
+    "\4\166\1\0\11\166\2\0\1\166\6\0\4\166\6\0"+
+    "\1\166\6\0\6\166\1\0\13\166\1\0\13\166\1\0"+
+    "\4\166\1\0\1\166\1\u0273\7\166\2\0\1\166\6\0"+
+    "\4\166\6\0\1\166\6\0\6\166\1\0\13\166\1\0"+
+    "\13\166\1\0\4\166\1\0\2\166\1\u0274\6\166\2\0"+
+    "\1\166\6\0\4\166\6\0\1\166\6\0\6\166\1\0"+
+    "\13\166\1\0\4\166\1\u0275\6\166\1\0\4\166\1\0"+
+    "\11\166\2\0\1\166\6\0\4\166\6\0\1\166\6\0"+
+    "\6\166\1\0\13\166\1\0\13\166\1\0\4\166\1\0"+
+    "\2\166\1\u0276\6\166\2\0\1\166\46\0\1\u0277\74\0"+
+    "\1\u0278\106\0\1\u0279\116\0\1\u027a\105\0\1\u027b\51\0"+
+    "\4\166\6\0\1\166\6\0\6\166\1\0\10\166\1\u027c"+
+    "\2\166\1\0\13\166\1\0\4\166\1\0\11\166\2\0"+
+    "\1\166\6\0\4\166\6\0\1\166\6\0\5\166\1\u027d"+
+    "\1\0\13\166\1\0\13\166\1\0\4\166\1\0\11\166"+
+    "\2\0\1\166\6\0\4\166\6\0\1\166\6\0\5\166"+
+    "\1\u027e\1\0\13\166\1\0\13\166\1\0\4\166\1\0"+
+    "\11\166\2\0\1\166\6\0\4\166\6\0\1\166\6\0"+
+    "\6\166\1\0\6\166\1\u027f\4\166\1\0\13\166\1\0"+
+    "\4\166\1\0\11\166\2\0\1\166\6\0\4\166\6\0"+
+    "\1\166\6\0\6\166\1\0\5\166\1\u0280\5\166\1\0"+
+    "\13\166\1\0\4\166\1\0\11\166\2\0\1\166\57\0"+
+    "\1\u0281\131\0\1\u0282\52\0\1\u0283\106\0\1\u0284\46\0"+
+    "\4\166\6\0\1\166\6\0\6\166\1\0\13\166\1\0"+
+    "\5\166\1\u0285\5\166\1\0\4\166\1\0\11\166\2\0"+
+    "\1\166\6\0\4\166\6\0\1\166\6\0\6\166\1\0"+
+    "\13\166\1\0\13\166\1\0\4\166\1\0\7\166\1\u0286"+
+    "\1\166\2\0\1\166\6\0\4\166\6\0\1\166\6\0"+
+    "\6\166\1\0\10\166\1\u0287\2\166\1\0\13\166\1\0"+
+    "\4\166\1\0\11\166\2\0\1\166\6\0\4\166\6\0"+
+    "\1\166\6\0\6\166\1\0\10\166\1\u0288\2\166\1\0"+
+    "\13\166\1\0\4\166\1\0\11\166\2\0\1\166\103\0"+
+    "\1\u0289\63\0\1\u0271\131\0\1\u027b\106\0\1\u028a\11\0"+
+    "\4\166\6\0\1\166\6\0\6\166\1\0\13\166\1\0"+
+    "\13\166\1\0\4\166\1\0\10\166\1\u028b\2\0\1\166"+
+    "\6\0\4\166\6\0\1\166\6\0\6\166\1\0\13\166"+
+    "\1\0\6\166\1\u0276\4\166\1\0\4\166\1\0\11\166"+
+    "\2\0\1\166\6\0\4\166\6\0\1\166\6\0\6\166"+
+    "\1\0\13\166\1\0\13\166\1\0\4\166\1\0\10\166"+
+    "\1\u0280\2\0\1\166\6\0\4\166\6\0\1\166\6\0"+
+    "\6\166\1\0\13\166\1\0\13\166\1\0\4\166\1\0"+
+    "\10\166\1\u028c\2\0\1\166\34\0\1\u0271\154\0\1\u028d"+
+    "\12\0\4\166\6\0\1\166\6\0\5\166\1\u0276\1\0"+
+    "\13\166\1\0\13\166\1\0\4\166\1\0\11\166\2\0"+
+    "\1\166\6\0\4\166\6\0\1\166\6\0\6\166\1\0"+
+    "\13\166\1\0\13\166\1\0\4\166\1\0\7\166\1\u028e"+
+    "\1\166\2\0\1\166\56\0\1\u0271\36\0\4\166\6\0"+
+    "\1\166\6\0\6\166\1\0\13\166\1\0\4\166\1\u0276"+
+    "\6\166\1\0\4\166\1\0\11\166\2\0\1\166";
+
+  /** 
+   * The transition table of the DFA
+   */
+  final private static int yytrans [] = yy_unpack(yy_packed);
+
+
+  /* error codes */
+  final private static int YY_UNKNOWN_ERROR = 0;
+  // final private static int YY_ILLEGAL_STATE = 1;
+  final private static int YY_NO_MATCH = 2;
+  final private static int YY_PUSHBACK_2BIG = 3;
+
+  /* error messages for the codes above */
+  final private static String YY_ERROR_MSG[] = {
+    "Unkown internal scanner error",		//$NON-NLS-1$
+    "Internal error: unknown state",		//$NON-NLS-1$
+    "Error: could not match input",		//$NON-NLS-1$
+    "Error: pushback value was too large"	//$NON-NLS-1$
+  };
+
+  /**
+   * YY_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+   */
+  private final static byte YY_ATTRIBUTE[] = {
+     1,  0,  0,  0,  0,  1,  0,  0,  1,  1,  1,  0,  1,  1,  1,  1, 
+     0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
+     1,  1,  1,  1,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0, 
+     0,  1,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  9,  1, 
+     9,  1,  1,  9,  9,  1,  1,  1,  1,  1,  1,  1,  1,  1,  9,  1, 
+     1,  1,  1,  9,  1,  1,  1,  1,  1,  1,  9,  1,  1,  9,  1,  1, 
+     1,  1,  9,  1,  1,  1,  1,  1,  1,  1,  9,  1,  1,  1,  1,  1, 
+     1,  1,  9,  1,  1,  1,  1,  1,  1,  9,  1,  1,  1,  1,  1,  1, 
+     1,  1,  9,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  9,  1,  1,  1,  1,  1, 
+     1,  9,  9,  1,  9,  1,  1,  1,  1,  1,  9,  1,  1,  1,  1,  9, 
+     1,  1,  1,  1,  9,  9,  1,  9,  3,  3,  3,  3,  3,  3,  9,  9, 
+     1,  1,  1,  9,  1,  1,  1,  1,  1,  9,  9,  1,  9,  3,  3,  3, 
+     3,  3,  3,  9,  9,  1,  1,  1,  9,  1,  1,  1,  9,  9,  1,  1, 
+     0,  1,  0,  9,  1,  2,  1,  2,  1,  0,  0,  0,  9,  1,  1,  1, 
+     9,  9,  0,  0,  9,  0,  0,  0,  0,  0,  0,  0,  0,  9,  1,  0, 
+     0,  1,  9,  0,  9,  0,  0,  9,  0,  0,  0,  9,  1,  1,  0,  1, 
+     0,  9,  0,  0,  0,  1,  1,  0,  0,  0,  0,  9,  0,  0,  0,  0, 
+     9,  0,  0,  0,  1,  0,  0,  1,  0,  0,  9,  0,  0,  1,  0,  0, 
+     9,  0,  0,  0,  1,  0,  1,  1,  0,  0,  9,  0,  0,  0,  1,  0, 
+     1,  1,  0,  0,  9,  9,  9,  0,  9,  9,  1,  1,  1,  1,  2, 13, 
+     3,  2,  2, 13,  3,  2,  0,  1,  1,  0,  1,  1,  1,  1,  2, 13, 
+     3,  2,  2, 13,  3,  2,  0,  1,  1,  0,  1,  1,  0,  9,  9,  9, 
+     0,  0,  1,  1,  1,  9,  0,  0, 13,  9, 13,  9,  9,  1,  1,  1, 
+     0,  0,  1,  3,  2,  2,  3,  2,  2,  0,  0,  0,  0,  0,  0,  1, 
+     0,  0,  1,  0,  1,  1,  1,  1,  1,  0,  1,  0,  1,  1,  1,  1, 
+     1,  0,  1,  1,  1,  1,  1,  0,  2,  3,  3,  3,  2,  2,  3,  3, 
+     3,  2,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  0,  0,  1,  1, 
+     1,  1,  2,  3,  3,  3,  2,  2,  3,  3,  3,  2,  1,  1,  1,  1, 
+     0,  0,  1,  1,  1,  1,  0,  0,  9,  9,  0,  1,  9,  0,  1,  1, 
+     1,  5, 13, 13,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  1,  1, 
+     9,  1,  3,  2,  3,  2,  1,  0,  9,  1,  0,  1,  3,  2,  3,  2, 
+     1,  0,  9,  1,  0,  0,  1,  1,  1,  1,  0,  0,  0,  0,  0,  1, 
+     1,  2,  2,  0,  0,  2,  2,  0,  0,  0,  1,  1,  1,  1,  0,  0, 
+     0,  9,  9,  1,  1,  2,  2,  1,  1,  2,  2,  1,  1,  0,  1,  1, 
+     1,  9,  9,  9,  1,  1,  2,  2,  2,  2,  0,  1,  1,  1,  1,  1, 
+     2,  2,  2,  2,  9,  1,  1,  1,  1,  3,  3,  3,  3,  1,  1,  1, 
+     1,  1,  1,  1,  1,  1,  0,  1,  0,  0,  0,  0,  0,  1,  1,  1, 
+     1,  1,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  0,  0,  1,  0, 
+     0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  9,  1,  1,  1,  1,  1, 
+     0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1
+  };
+
+  /** the input device */
+  private java.io.Reader yy_reader;
+
+  /** the current state of the DFA */
+  private int yy_state;
+
+  /** the current lexical state */
+  private int yy_lexical_state = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private char yy_buffer[] = new char[16384];
+
+  /** the textposition at the last accepting state */
+  private int yy_markedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int yy_pushbackPos;
+
+  /** the current text position in the buffer */
+  private int yy_currentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int yy_startRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int yy_endRead;
+
+  /** number of newlines encountered up to the start of the matched text */
+  private int yyline;
+
+  /** the number of characters up to the start of the matched text */
+  private int yychar;
+
+  /**
+   * the number of characters from the last newline up to the start of the 
+   * matched text
+   */
+  // private int yycolumn; 
+
+  /** 
+   * yy_atBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  // private boolean yy_atBOL;
+
+  /** yy_atEOF == true <=> the scanner has returned a value for EOF */
+  private boolean yy_atEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean yy_eof_done;
+
+  /* user code: */
+	private int fTokenCount = 0;
+ 
+	// required holders for white-space compacting
+	private boolean fShouldLoadBuffered = false;
+	private String fBufferedContext = null;
+	private int fBufferedStart = 1;
+	private int fBufferedLength = 0;
+	private ContextRegionContainer fBufferedEmbeddedContainer = null;
+	private String f_context = null;
+
+	// state stack for handling embedded regions
+	private IntStack fStateStack = new IntStack();
+	// a "hint" as to what an embedded region should be evaluated
+	private String fEmbeddedHint = UNDEFINED;
+	// a "hint" as to what state to enter once an embedded region has
+	//   been completed
+	private int fEmbeddedPostState = YYINITIAL;
+	// the container used to create embedded regions
+	private ContextRegionContainer fEmbeddedContainer = null;
+	private static final String PROXY_CONTEXT = "PROXY_CONTEXT";
+
+	private String context = null;
+	private int start = 0;
+	private int textLength = 0;
+	private int length = 0;
+
+	// offset for tracking position specific block tags
+	private int fOffset = 0;
+	
+	// the name of the current tag being opened
+	private String fCurrentTagName = null;
+
+	// the name of the current tag inside of an embedded region
+	private String internalTagName = null;
+	private String internalContext = null;
+
+	// the list of tag name BlockMarkers
+	private List fBlockMarkers = new ArrayList(0);
+	private List fNestablePrefixes = new ArrayList(1);
+	
+	// where the last internal container block was found
+	private int fLastInternalBlockStart = -1;
+
+	// required to not seek text blocks on an end tag
+	private boolean fIsBlockingEnabled = false;
+	private boolean fIsCaseSensitiveBlocking = true;
+
+	private static final boolean fForbidJSP = false;
+	
+	private int fELlevel = 0;
+
+	private JSPParserRegionFactory fRegionFactory = new JSPParserRegionFactory();
+
+	/**
+	 * user method 
+	 */
+	public final void addBlockMarker(BlockMarker marker) {
+		if(containsTagName(marker.getTagName()))
+			return;
+		fBlockMarkers.add(marker);
+	}
+	/**
+	 * user method
+	 */
+	public final void addNestablePrefix(TagMarker marker) {
+		fNestablePrefixes.add(marker);
+	}
+	/* user method */
+	public List getNestablePrefixes() {
+		return fNestablePrefixes;
+	}
+	/**
+	 * user method
+	 */
+	private boolean isNestable(String tagName) {
+		//Iterator blocks = fNestablePrefixes.iterator();
+		//while(blocks.hasNext()) {
+		//	TagMarker marker = (TagMarker)blocks.next();
+		//	String markerName = marker.getTagName();
+		//	if(tagName.length() > markerName.length() + 1 && tagName.startsWith(markerName) && tagName.charAt(markerName.length()) == ':') {
+		//		return marker.isGlobal() || getOffset() >= marker.getMarker().getStart();
+		//	}
+		//}
+		//return false;
+		return true;
+	}
+	/**
+	 * user method 
+	 */
+	public final void removeNestablePrefix(String name) {
+		if (fNestablePrefixes != null) {
+			Iterator nestables = fNestablePrefixes.iterator();
+			while (nestables.hasNext()) {
+				if (((TagMarker) nestables.next()).getTagName().equalsIgnoreCase(name))
+					nestables.remove();
+			}
+		}
+	}
+	/**
+	 * user method 
+	 */
+	public final void removeBlockMarker(BlockMarker marker) {
+		fBlockMarkers.remove(marker);
+	}
+	/**
+	 * user method 
+	 */
+	public final void removeBlockMarker(String tagname) {
+		if (fBlockMarkers != null) {
+			Iterator blocks = fBlockMarkers.iterator();
+			while (blocks.hasNext()) {
+				if (((BlockMarker) blocks.next()).getTagName().equals(tagname))
+					blocks.remove();
+			}
+		}
+	}
+	/* user method */
+	private final void assembleEmbeddedTagSequence(String startType, String endTagName) {
+		assembleEmbeddedContainer(startType, null, endTagName);
+	}
+	/* user method */
+	private final void assembleEmbeddedContainer(String startType, String[] endTypes) {
+		assembleEmbeddedContainer(startType, endTypes, null);
+	}
+	/* user method */
+	private final void assembleEmbeddedContainer(String startType, String endType) {
+		assembleEmbeddedContainer(startType, new String[]{endType}, null);
+	}
+	/**
+	 *  user method 
+	 * 
+	 * Assembles an embedded container beginning with the given startType as
+	 * the first ContextRegion within it and of the type fEmbeddedHint.  The
+	 * endTypes[] array contains the context types that will cause a successful
+	 * exit.  Use of the endTagName parameter alters this behavior to force an
+	 * exit on an XML_TAG_CLOSE after seeing an XML_TAG_NAME whose significant
+	 * text matches the endTagName String.  All contents in between are
+	 * insignificant, and yes, this means comments are allowed inside.
+	 **/
+	private final void assembleEmbeddedContainer(String startType, String[] endTypes, String endTagName) {
+		// the context of the region being added to the embedded container
+		internalContext = startType;
+		// keep track of where this container began; to provide relative indeces for the regions
+		int containerStart = yychar;
+		boolean notFinished = true;
+		// keep track of where we seem to be so that the endTagName can be checked
+		boolean isInEndTag = false;
+		boolean isInFirstTag = true;
+		// create the embedded container and setup its "type"
+		if (fEmbeddedContainer == null) {
+			fEmbeddedContainer = new ContextRegionContainer();
+			fEmbeddedContainer.setType(fEmbeddedHint);
+			fEmbeddedContainer.setStart(containerStart);
+			// TODO: parent region needs to be set .... but not sure where to get it from 
+			//		fEmbeddedContainer.setParent(parentRegion);
+		}
+		containerStart = fEmbeddedContainer.getStart();
+		while (notFinished) {
+			// add the region to the container
+			if (internalContext != null && internalContext != PROXY_CONTEXT) {
+				ITextRegion newToken = fRegionFactory.createToken(internalContext, yychar - containerStart, yylength(), yylength());
+				fEmbeddedContainer.getRegions().add(newToken);
+				fEmbeddedContainer.setLength(fEmbeddedContainer.getLength() + yylength());
+				fEmbeddedContainer.setTextLength(fEmbeddedContainer.getTextLength() + yylength());
+				// DW, 4/16/2003 token regions no longer have parents
+				//newToken.setParent(fEmbeddedContainer);
+			}
+			try {
+				// longscan determines whether to attempt a blockTagScan within the embedded container
+				boolean longscan = false;
+				// save the tokenizer state in case of a block tag scan
+				int previousState = yystate();
+				String previousCurrentTagName = fCurrentTagName;
+				int previousPostState = fEmbeddedPostState;
+				String previousEmbeddedHint = fEmbeddedHint;
+				// determine if a block tag scan is necessary
+				if (internalContext == XML_TAG_NAME) {
+					internalTagName = yytext();
+					if(!isNestable(internalTagName)) {
+						internalTagName = null;
+						// snagged a tag name we shouldn't have
+						fEmbeddedPostState = ST_ABORT_EMBEDDED;
+						notFinished = false;
+					}
+				}
+				else if (internalContext == XML_TAG_OPEN || internalContext == XML_END_TAG_OPEN) {
+					internalTagName = null;
+				}
+				// do upkeep for endTagName usage; must be here since the next token could be the close
+				if (internalContext == XML_END_TAG_OPEN) {
+					isInEndTag = true;
+				} else if (internalContext == XML_TAG_CLOSE) {
+					isInFirstTag = isInEndTag = false;
+				} else {
+				 	ITextRegionList embeddedRegions = fEmbeddedContainer.getRegions();
+					if (embeddedRegions.size() > 2 && (embeddedRegions.get(embeddedRegions.size()-1)).getType() == XML_TAG_CLOSE && (embeddedRegions.get(embeddedRegions.size() - 3)).getType() == XML_TAG_OPEN && internalTagName != null) {
+						if (containsTagName(internalTagName)) {
+							longscan = true;
+							yybegin(ST_BLOCK_TAG_SCAN);
+						}
+					}
+				}
+				if (longscan)
+					fCurrentTagName = internalTagName;
+				// read the next region and context
+				internalContext = primGetNextToken();
+				if (longscan) {
+					// Returning from a block tag scan requires restoring some state variables
+					// as well as handling the block region and setting up for normal scanning
+					// inside the embedded container
+					ITextRegion newToken = fRegionFactory.createToken(internalContext, yychar - containerStart, yylength(), yylength());
+					fEmbeddedContainer.getRegions().add(newToken);
+					fEmbeddedContainer.setLength(fEmbeddedContainer.getLength() + yylength());
+					fEmbeddedContainer.setTextLength(fEmbeddedContainer.getTextLength() + yylength());
+					// DW, 4/16/2003 token regions no longer have parents
+					// newToken.setParent(fEmbeddedContainer);
+					longscan = false;
+					fEmbeddedPostState = previousPostState;
+					fEmbeddedHint = previousEmbeddedHint;
+					fCurrentTagName = previousCurrentTagName;
+					yybegin(previousState);
+					internalContext = primGetNextToken();
+				}
+			} catch (IOException e) {
+				// primGetNextToken() calls may throw an IOException
+				// catch and do nothing since the isEOF check below
+				// will properly exit if the input was too short
+			} catch (Exception f) {
+				// some other exception happened; never should
+				Logger.logException(f);
+			}
+			boolean isEndingType = yystate() == ST_ABORT_EMBEDDED;
+			if(!isEndingType) {
+				// check for ending context
+				if (endTagName == null) {
+					for (int i = 0; i < endTypes.length; i++) {
+						isEndingType = isEndingType || (internalContext == endTypes[i]);
+					}
+				}
+				else {
+					isEndingType = ((isInEndTag && internalContext == XML_TAG_CLOSE) || (isInFirstTag && internalContext == XML_EMPTY_TAG_CLOSE)) && internalTagName != null && internalTagName.equals(endTagName);
+				}
+			}
+			ITextRegionList embeddedList = fEmbeddedContainer.getRegions();
+			notFinished = notFinished && ((!isEndingType) && !isEOF() && (endTagName != null || internalContext != UNDEFINED) && !(internalContext == PROXY_CONTEXT && (embeddedList.get(embeddedList.size()-1)).getType() == UNDEFINED));
+		}
+		// finish adding the last context
+		if (internalContext != null && internalContext != PROXY_CONTEXT) {
+			ITextRegion newToken = fRegionFactory.createToken(internalContext, yychar - containerStart, yylength(), yylength());
+			fEmbeddedContainer.getRegions().add(newToken);
+			// DW, 4/16/2003 token regions no longer have parents
+			//newToken.setParent(fEmbeddedContainer);
+			fEmbeddedContainer.setLength(yychar - containerStart + yylength());
+			fEmbeddedContainer.setTextLength(yychar - containerStart + yylength());
+		}
+		yybegin(fEmbeddedPostState);
+	}
+	/* user method */
+	public final boolean isCaseSensitiveBlocking() {
+		return fIsCaseSensitiveBlocking;
+	}
+	/* user method */
+	public final void setCaseSensitiveBlocking(boolean newValue) {
+		fIsCaseSensitiveBlocking = newValue;
+	}
+	/* user method */
+	public boolean getBlockMarkerAllowsJSP() {
+		return getBlockMarkerAllowsJSP(fCurrentTagName);
+	}
+	/* user method */
+	public boolean getBlockMarkerAllowsJSP(String name) {
+		Iterator iterator = fBlockMarkers.iterator();
+		while(iterator.hasNext()) {
+			BlockMarker marker = (BlockMarker)iterator.next();
+			boolean casesensitive = marker.isCaseSensitive();
+			if(casesensitive && marker.getTagName().equals(name))
+				return marker.allowsJSP();
+			else if(!casesensitive && marker.getTagName().equalsIgnoreCase(name))
+				return marker.allowsJSP();
+		}
+		return true;
+	}
+	/* user method */
+	public boolean getBlockMarkerCaseSensitivity() {
+		return getBlockMarkerCaseSensitivity(fCurrentTagName);
+	}
+	public boolean getBlockMarkerCaseSensitivity(String name) {
+		Iterator iterator = fBlockMarkers.iterator();
+		while(iterator.hasNext()) {
+			BlockMarker marker = (BlockMarker)iterator.next();
+			boolean casesensitive = marker.isCaseSensitive();
+			if(casesensitive && marker.getTagName().equals(name))
+				return casesensitive;
+			else if(!casesensitive && marker.getTagName().equalsIgnoreCase(name))
+				return casesensitive;
+		}
+		return true;
+	}
+	/* user method */
+	public String getBlockMarkerContext() {
+		return getBlockMarkerContext(fCurrentTagName);
+	}
+	/* user method */
+	public String getBlockMarkerContext(String name) {
+		Iterator iterator = fBlockMarkers.iterator();
+		while(iterator.hasNext()) {
+			BlockMarker marker = (BlockMarker)iterator.next();
+			if(marker.getTagName().equals(name))
+				return marker.getContext();
+		}
+		return BLOCK_TEXT;
+	}
+	/* user method */
+	public List getBlockMarkers() {
+		return fBlockMarkers;
+	}
+	/* user method */
+	public final int getOffset() {
+		return fOffset + yychar;
+	}
+	private final boolean isBlockMarker() {
+		return isBlockMarker(fCurrentTagName);
+	}
+	private final boolean isBlockMarker(String tagName) {
+		if (!fIsBlockingEnabled)
+			return false;
+		return containsTagName(tagName);
+	}
+	/**
+	 * user method
+	 */
+	public final void beginBlockTagScan(String newTagName) {
+		beginBlockMarkerScan(newTagName, BLOCK_TEXT);
+	}
+	/**
+	 * user method
+	 *
+	 * Special tokenizer setup.  Allows tokenization to be initiated at the
+	 * start of a text block within a "newTagName" tag.
+	 *
+	 * Example: 
+	 *	Tokenizer toker = new Tokenizer();
+	 *	toker.setCaseSensitiveBlocking(false);
+	 *	toker.reset(new java.io.StringReader("afiuhqwkejhtasihgalkwhtq</scripter></scr></script>asgdasga"));
+	 *	toker.beginBlockMarkerScan("script", BLOCK_TEXT);
+	 *	toker.getRegions(); 
+	 *
+	 * Returns:
+	 *	BLOCK_TEXT: 0-40
+	 *	XML_END_TAG_OPEN: 41-42
+	 *	XML_TAG_NAME: 43-48
+	 *	XML_TAG_CLOSE: 49-49
+	 *	XML_CONTENT: 50-57
+	 *
+	 */
+	public final void beginBlockMarkerScan(String newTagName, String blockcontext) {
+		yybegin(ST_BLOCK_TAG_SCAN);
+		fCurrentTagName = newTagName;
+	}
+
+/**
+ * Method doScan.
+ * 
+ * Returns a context region for all of the text from the current position upto the end of input or
+ * to right *before* the first occurence of searchString
+ * 
+ * @param searchString - target string to search for ex.: "-->", "</tagname"
+ * @param requireTailSeparator - whether the target must be immediately followed by whitespace or '>'
+ * @param allowJSP - check for and allow for JSP markup <%%>
+ * @param context - the context of the scanned region if non-zero length
+ * @param exitState - the state to go to if the region was of non-zero length
+ * @param abortState - the state to go to if the searchString was found immediately
+ * @return String - the context found: the desired context on a non-zero length match, the abortContext on immediate success
+ * @throws IOException
+ */
+private final String doScan(String searchString, boolean requireTailSeparator, boolean allowJSP, boolean allowCDATA, String searchContext, int exitState, int immediateFallbackState) throws IOException {
+	boolean stillSearching = true;
+	// Disable further block (probably)
+	fIsBlockingEnabled = false;
+	int searchStringLength = searchString.length();
+	int n = 0;
+	char lastCheckChar;
+	int i;
+	boolean same = false;
+	// Check for JSP starts ("<%") if the tag is global like SCRIPT or STYLE
+	boolean checkJSPs = allowJSP && !fForbidJSP;
+	boolean checkedForJSPsOnce = !checkJSPs;
+	boolean checkedJSPsAtStartOnce = false;
+	
+	while (stillSearching) {
+		n = 0;
+		// Ensure that enough data from the input exists to compare against the search String.
+		n = yy_advance();
+		while(n != YYEOF && yy_currentPos < searchStringLength)
+			n = yy_advance();
+//		c = (char) n;
+		// If the input was too short or we've exhausted the input, stop immediately.
+		if (n == YYEOF && checkedForJSPsOnce) {
+			stillSearching = false;
+		}
+		else {
+			/**
+			 * Look for starting JSPs "<%"
+			 */
+			checkedForJSPsOnce = true;
+			// 1) yy_currentPos - searchStringLength : There's at least searchStringLength of input available; once that's read, check for JSPs
+			// ---
+			// Look for a JSP beginning at current-searchStringLength; if so, backup and switch scanner states to handle it.
+			// Ensure that we've not encountered a complete block (<%%>) that was *shorter* than the closeTagString and
+			// thus found twice at current-targetLength [since the first scan would have come out this far anyway].
+			if(checkJSPs && yy_currentPos > searchStringLength && yy_currentPos - searchStringLength != fLastInternalBlockStart && 
+				yy_buffer[yy_currentPos - searchStringLength] == '<' && yy_buffer[yy_currentPos - searchStringLength + 1] == '%') {
+				fLastInternalBlockStart = yy_markedPos = yy_currentPos - searchStringLength;
+				yy_currentPos = yy_markedPos + 1;
+				int resumeState = yystate();
+				yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);
+				if(yy_markedPos == yy_startRead) {
+					String jspContext = primGetNextToken();
+					yybegin(resumeState);
+					return jspContext;
+				}
+				return searchContext;
+			}
+			// 2) yy_currentPos - jspstarter.length : There's not searchStringLength of input available; check for a JSP 2 spots back in what we could read
+			// ---
+			// Look for a JSP beginning at the current position; this case wouldn't be handled by the preceding section
+			// since it relies upon *having* closeTagStringLength amount of input to work as designed.  Must be sure we don't
+			// spill over the end of the buffer while checking.
+			else if(checkJSPs && yy_startRead != fLastInternalBlockStart && yy_currentPos > 0 && yy_currentPos < yy_buffer.length - 1 &&
+					yy_buffer[yy_currentPos - 1] == '<' && yy_buffer[yy_currentPos] == '%') {
+				fLastInternalBlockStart = yy_markedPos = yy_currentPos - 1;
+				yy_currentPos = yy_markedPos + 1;
+				int resumeState = yystate();
+				yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);
+				if(yy_markedPos == yy_startRead) {
+					String jspContext = primGetNextToken();
+					yybegin(resumeState);
+					return jspContext;
+				}
+				return searchContext;
+			}
+			// 3) yy_currentPos..(yy_currentPos+jspStartlength-1) : Check at the start of the block one time
+			// ---
+			// Look for a JSP beginning immediately in the block area; this case wouldn't be handled by the preceding section
+			// since it relies upon yy_currentPos equaling exactly the previous end +1 to work as designed.
+			else if(checkJSPs && !checkedJSPsAtStartOnce && yy_startRead != fLastInternalBlockStart && yy_startRead > 0 &&
+					yy_startRead < yy_buffer.length - 1 && yy_buffer[yy_startRead] == '<' && yy_buffer[yy_startRead + 1] == '%') {
+				checkedJSPsAtStartOnce = true;
+				fLastInternalBlockStart = yy_markedPos = yy_startRead;
+				yy_currentPos = yy_markedPos + 1;
+				int resumeState = yystate();
+				yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);
+				if(yy_markedPos == yy_startRead) {
+					String jspContext = primGetNextToken();
+					yybegin(resumeState);
+					return jspContext;
+				}
+				return searchContext;
+			}
+
+
+			/**
+			 * Look for starting CDATA "<![CDATA["
+			 */
+			// 1) yy_currentPos - searchStringLength: There's at least searchStringLength of input available; once that's read, check for CDATA
+			// ---
+			// Look for a CDATA beginning at current-searchStringLength; if so, backup and switch scanner states to handle it.
+			// Ensure that we've not encountered a complete block (<[!CDATA[]]>) that was *shorter* than the closeTagString and
+			// thus found twice at current-targetLength [since the first scan would have come out this far anyway].
+/*			if(checkCDATA && yy_currentPos > searchStringLength && yy_currentPos + searchStringLength < yy_buffer.length && yy_currentPos - searchStringLength != fLastInternalBlockStart && 
+				charsMatch(cdataStarter, yy_buffer, 0, yy_currentPos - searchStringLength)) {
+				fLastInternalBlockStart = yy_markedPos = yy_currentPos - searchStringLength;
+				yy_currentPos = yy_markedPos + 1;
+				int resumeState = yystate();
+				// go to a state where CDATA can be found
+				if (fEmbeddedContainer == null) {
+					fEmbeddedContainer = new ContextRegionContainer();
+					fEmbeddedContainer.setType(searchContext);
+					fEmbeddedContainer.setStart(yychar);
+				}
+				ITextRegion newToken = fRegionFactory.createToken(searchContext, yychar, yylength(), yylength());
+				fEmbeddedContainer.getRegions().add(newToken);
+				fEmbeddedContainer.setLength(fEmbeddedContainer.getLength() + yylength());
+				fEmbeddedContainer.setTextLength(fEmbeddedContainer.getTextLength() + yylength());
+				yybegin(YYINITIAL);
+				String context = primGetNextToken();
+				if(context.equals(XMLRegionContexts.XML_CDATA_OPEN)) {
+					assembleEmbeddedContainer(XMLRegionContexts.XML_CDATA_OPEN, XMLRegionContexts.XML_CDATA_CLOSE);
+				}
+				yybegin(resumeState);
+				return searchContext;
+			}
+*//*
+			// 2) yy_currentPos - cdataStarter.length: There's not searchStringLength of input available; check for a CDATA right here spots back in what we could read
+			// ---
+			// Look for a JSP beginning at the current position; this case wouldn't be handled by the preceding section
+			// since it relies upon *having* closeTagStringLength amount of input to work as designed.  Must be sure we don't
+			// spill over the end of the buffer while checking.
+			else if(checkCDATA && yy_startRead != fLastInternalBlockStart && yy_currentPos > 0 && yy_currentPos < yy_buffer.length - 1 &&
+					yy_buffer[yy_currentPos - 1] == '<' && yy_buffer[yy_currentPos] == '%') {
+				fLastInternalBlockStart = yy_markedPos = yy_currentPos - 1;
+				yy_currentPos = yy_markedPos + 1;
+				int resumeState = yystate();
+				yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);
+				if(yy_markedPos == yy_startRead) {
+					String jspContext = primGetNextToken();
+					yybegin(resumeState);
+					return jspContext;
+				}
+				return searchContext;
+			}
+			// 3) yy_currentPos : Check at the start of the block one time
+			// ---
+			// Look for a JSP beginning immediately in the block area; this case wouldn't be handled by the preceding section
+			// since it relies upon yy_currentPos equaling exactly the previous end +1 to work as designed.
+			else if(checkCDATA && !checkedForCDATAOnce && yy_startRead != fLastInternalBlockStart && yy_startRead > 0 &&
+					yy_startRead < yy_buffer.length - 1 && yy_buffer[yy_startRead] == '<' && yy_buffer[yy_startRead + 1] == '%') {
+				checkedForCDATAOnce = true;
+				fLastInternalBlockStart = yy_markedPos = yy_startRead;
+				yy_currentPos = yy_markedPos + 1;
+				int resumeState = yystate();
+				yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);
+				if(yy_markedPos == yy_startRead) {
+					String jspContext = primGetNextToken();
+					yybegin(resumeState);
+					return jspContext;
+				}
+				return searchContext;
+			}
+*/
+			// Check the characters in the target versus the last targetLength characters read from the buffer
+			// and see if it matches
+			if (n == YYEOF) {
+				stillSearching = false;
+			}
+			else {
+				same = true;
+				// safety check for array accesses
+				if(yy_currentPos >= searchStringLength && yy_currentPos <= yy_buffer.length) {
+					for(i = 0; i < searchStringLength; i++) {
+						if(same && fIsCaseSensitiveBlocking)
+							same = yy_buffer[i + yy_currentPos - searchStringLength] == searchString.charAt(i);
+						else if(same && !fIsCaseSensitiveBlocking)
+							same = Character.toLowerCase(yy_buffer[i + yy_currentPos - searchStringLength]) == Character.toLowerCase(searchString.charAt(i));
+					}
+				}
+				// safety check failed; no match is possible right now
+				else {
+					same = false;
+				}
+			}
+			if (same && requireTailSeparator && yy_currentPos < yy_buffer.length) {
+				// Additional check for close tags to ensure that targetString="</script" doesn't match
+				// "</scriptS"
+				lastCheckChar = yy_buffer[yy_currentPos];
+				// Succeed on "</script>" and "</script "
+				if(lastCheckChar == '>' || Character.isWhitespace(lastCheckChar))
+					stillSearching = false;
+			}
+			else {
+				stillSearching = !same || (yy_currentPos < yy_startRead + searchStringLength);
+			}
+		}
+	}
+	if (n != YYEOF || same) {
+		// We've stopped short of the end or definitely found a match
+		yy_markedPos = yy_currentPos - searchStringLength;
+		yy_currentPos = yy_markedPos + 1;
+		// If the searchString occurs at the very beginning of what would have
+		// been a Block, resume scanning normally immediately
+		if (yy_markedPos == yy_startRead) {
+			yybegin(immediateFallbackState);
+			return primGetNextToken();
+		}
+	}
+	else {
+		// We ran through the rest of the input
+		yy_markedPos = yy_currentPos;
+		yy_currentPos++;
+	}
+	yybegin(exitState);
+	// If the ending occurs at the very beginning of what would have
+	// been a Block, resume scanning normally immediately
+	if(yy_markedPos == yy_startRead)
+		return primGetNextToken();
+	return searchContext;
+}
+/**
+ * user method 
+ * does a lookahead for the current tag name
+ */
+private final String doBlockTagScan() throws IOException {
+	fIsCaseSensitiveBlocking = getBlockMarkerCaseSensitivity();
+	return doScan("</" + fCurrentTagName, true, getBlockMarkerAllowsJSP(), true, getBlockMarkerContext(fCurrentTagName), YYINITIAL, YYINITIAL);
+}
+	/**
+	 * user method
+	 *
+	 * Converts the raw context String returned by the primGetNextToken()
+	 * method into a full ITextRegion by pulling in values for the
+	 * current offset within the scanning text.
+	 *
+	 * Returns null when EOF is encountered and attaches intermittently
+	 * discovered whitespace onto the end of useful regions.
+	 *
+	 * Note that this algorithm caches the token following the one being returned
+	 * so that whitespace can be collapsed.
+	 */
+	public final ITextRegion getNextToken() throws IOException {
+		fEmbeddedContainer = null;
+		// load the starting non-whitespace token (assume that it is so)
+		if (fShouldLoadBuffered) {
+			if (fBufferedEmbeddedContainer != null) {
+				ITextRegion container = fBufferedEmbeddedContainer;
+				fBufferedEmbeddedContainer = null;
+				fShouldLoadBuffered = false;
+				return container;
+			}
+			context = fBufferedContext;
+			start = fBufferedStart;
+			textLength = length = fBufferedLength;
+			fShouldLoadBuffered = false;
+		} else {
+			context = primGetNextToken();
+			if (context == PROXY_CONTEXT) {
+				return fEmbeddedContainer;
+			} else if (context == XML_TAG_NAME || f_context == JSP_ROOT_TAG_NAME || f_context == JSP_DIRECTIVE_NAME) {
+				if(containsTagName(yy_buffer, yy_startRead, yy_markedPos-yy_startRead))
+					fCurrentTagName = yytext();
+				else
+					fCurrentTagName = null;
+			} else if (context == XML_TAG_OPEN) {
+				fIsBlockingEnabled = true;
+			} else if (context == XML_END_TAG_OPEN) {
+				fIsBlockingEnabled = false;
+			}
+			start = yychar;
+			textLength = length = yylength();
+			if (yy_atEOF) {
+				fTokenCount++;
+				return null;
+			}
+		}
+		// store the next token
+		f_context = primGetNextToken();
+		if (f_context == PROXY_CONTEXT) {
+			fBufferedEmbeddedContainer = fEmbeddedContainer;
+			fShouldLoadBuffered = true;
+		} else if (f_context == XML_TAG_NAME || f_context == JSP_ROOT_TAG_NAME || f_context == JSP_DIRECTIVE_NAME) {
+			if(containsTagName(yy_buffer, yy_startRead, yy_markedPos-yy_startRead))
+				fCurrentTagName = yytext();
+			else
+				fCurrentTagName = null;
+		} else if (f_context == XML_TAG_OPEN) {
+			fIsBlockingEnabled = true;
+		} else if (f_context == XML_END_TAG_OPEN) {
+			fIsBlockingEnabled = false;
+		}
+		fBufferedContext = f_context;
+		fBufferedStart = yychar;
+		fBufferedLength = yylength();
+		fShouldLoadBuffered = true;
+		if (fBufferedContext == WHITE_SPACE) {
+			fShouldLoadBuffered = false;
+			length += fBufferedLength;
+		}
+		if (context == null) {
+			// EOF
+			if (Debug.debugTokenizer) {
+				System.out.println(getClass().getName() + " discovered " + fTokenCount + " tokens."); //$NON-NLS-2$//$NON-NLS-1$
+			}
+			return null;
+		}
+		fTokenCount++;
+		return fRegionFactory.createToken(context, start, textLength, length, null, fCurrentTagName);
+	}
+	/* user method */
+	public JSPTokenizer(){
+		super();
+	}
+	/* user method */
+	public JSPTokenizer(char[] charArray){
+			this(new CharArrayReader(charArray));
+	}
+	/* user method */
+	public void reset(char[] charArray) {
+		reset(new CharArrayReader(charArray), 0);
+	}
+	/* user method */
+	public void reset(char[] charArray, int newOffset) {
+		reset(new CharArrayReader(charArray), newOffset);
+	}
+	/* user method */
+	public void reset(java.io.InputStream in) {
+		reset(new java.io.InputStreamReader(in), 0);
+	}
+	/* user method */
+	public void reset(java.io.InputStream in, int newOffset) {
+		reset(new java.io.InputStreamReader(in), newOffset);
+	}
+	/* user method */
+	public void reset(java.io.Reader in) {
+		reset(in, 0);
+	}
+	/**
+	 * user method *
+	 *
+	 * Reset internal counters and vars to "newly created" values, in the hopes
+	 * that resetting a pre-existing tokenizer is faster than creating a new one.
+	 *
+	 * This method contains code blocks that were essentially duplicated from the
+	 * <em>generated</em> output of this specification before this method was
+	 * added.  Those code blocks were under the above copyright.
+	 */
+	public void reset(java.io.Reader in, int newOffset) {
+		if (Debug.debugTokenizer) {
+			System.out.println("resetting tokenizer");//$NON-NLS-1$
+		}
+		fOffset = newOffset;
+	
+		/* the input device */
+		yy_reader = in;
+	
+		/* the current state of the DFA */
+		yy_state = 0;
+	
+		/* the current lexical state */
+		yy_lexical_state = YYINITIAL;
+	
+		/* this buffer contains the current text to be matched and is
+		the source of the yytext() string */
+		java.util.Arrays.fill(yy_buffer, (char)0);
+	
+		/* the textposition at the last accepting state */
+		yy_markedPos = 0;
+	
+		/* the textposition at the last state to be included in yytext */
+		yy_pushbackPos = 0;
+	
+		/* the current text position in the buffer */
+		yy_currentPos = 0;
+	
+		/* startRead marks the beginning of the yytext() string in the buffer */
+		yy_startRead = 0;
+	
+		/** 
+		 * endRead marks the last character in the buffer, that has been read
+		 * from input 
+		 */
+		yy_endRead = 0;
+	
+		/* number of newlines encountered up to the start of the matched text */
+		yyline = 0;
+	
+		/* the number of characters up to the start of the matched text */
+		yychar = 0;
+	
+		/* yy_atEOF == true <=> the scanner has returned a value for EOF */
+		yy_atEOF = false;
+	
+		/* denotes if the user-EOF-code has already been executed */
+		yy_eof_done = false;
+	
+	
+		/* user vars: */
+		fTokenCount = 0;
+	 
+		fShouldLoadBuffered = false;
+		fBufferedContext = null;
+		fBufferedStart = 1;
+		fBufferedLength = 0;
+		fStateStack = new IntStack();
+	
+		fLastInternalBlockStart = -1;
+	
+		context = null;
+		start = 0;
+		textLength = 0;
+		length = 0;
+	
+		fEmbeddedContainer = null;
+		
+		fELlevel = 0;
+	}
+	/**
+	 * user method
+	 *
+	 */
+	public BlockTokenizer newInstance() {
+		JSPTokenizer newInstance = new JSPTokenizer();
+		// global tagmarkers can be shared; they have no state and 
+		// are never destroyed (e.g. 'release')
+		for(int i = 0; i < fBlockMarkers.size(); i++) {
+			BlockMarker blockMarker = (BlockMarker) fBlockMarkers.get(i);
+			if(blockMarker.isGlobal())
+				newInstance.addBlockMarker(blockMarker);
+		}
+		for(int i = 0; i < fNestablePrefixes.size(); i++) {
+			TagMarker marker = (TagMarker) fNestablePrefixes.get(i);
+			if(marker.isGlobal())
+				newInstance.addNestablePrefix(marker);
+		}
+		return newInstance;
+	}
+	/* user method */
+	private final String scanXMLCommentText() throws IOException {
+		// Scan for '-->' and return the text up to that point as
+		//   XML_COMMENT_TEXT unless the string occurs IMMEDIATELY, in which
+		//  case change to the ST_XML_COMMENT_END state and return the next
+		//  context as usual.
+		return doScan("-->", false, true, true, XML_COMMENT_TEXT, ST_XML_COMMENT_END, ST_XML_COMMENT_END);
+	}
+	/* user method */
+	private final String scanJSPCommentText() throws IOException {
+		// Scan for '--%>' and return the text up to that point as
+		//   JSP_COMMENT_TEXT unless the string occurs IMMEDIATELY, in which
+		//  case change to the ST_JSP_COMMENT_END state and return the next
+		//  context as usual.
+		return doScan("--%>", false, false, true, JSP_COMMENT_TEXT, ST_JSP_COMMENT_END, ST_JSP_COMMENT_END);
+	}
+
+
+  /**
+   * Creates a new scanner
+   * There is also a java.io.InputStream version of this constructor.
+   *
+   * @param   in  the java.io.Reader to read input from.
+   */
+  public JSPTokenizer(java.io.Reader in) {
+    this.yy_reader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  public JSPTokenizer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed DFA transition table.
+   *
+   * @param packed   the packed transition table
+   * @return         the unpacked transition table
+   */
+  private static int [] yy_unpack(String packed) {
+    int [] trans = new int[31595];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 8206) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      value--;
+      do trans[j++] = value; while (--count > 0);
+    }
+    return trans;
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] yy_unpack_cmap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 1376) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+
+  /**
+   * Gets the next input character.
+   *
+   * @return      the next character of the input stream, EOF if the
+   *              end of the stream is reached.
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  private int yy_advance() throws java.io.IOException {
+
+    /* standard case */
+    if (yy_currentPos < yy_endRead) return yy_buffer[yy_currentPos++];
+
+    /* if the eof is reached, we don't need to work hard */ 
+    if (yy_atEOF) return YYEOF;
+
+    /* otherwise: need to refill the buffer */
+
+    /* first: make room (if you can) */
+    if (yy_startRead > 0) {
+      System.arraycopy(yy_buffer, yy_startRead, 
+                       yy_buffer, 0, 
+                       yy_endRead-yy_startRead);
+
+      /* translate stored positions */
+      yy_endRead-= yy_startRead;
+      yy_currentPos-= yy_startRead;
+      yy_markedPos-= yy_startRead;
+      yy_pushbackPos-= yy_startRead;
+      yy_startRead = 0;
+    }
+
+    /* is the buffer big enough? */
+    if (yy_currentPos >= yy_buffer.length) {
+      /* if not: blow it up */
+      char newBuffer[] = new char[yy_currentPos*2];
+      System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);
+      yy_buffer = newBuffer;
+    }
+
+    /* finally: fill the buffer with new input */
+    int numRead = yy_reader.read(yy_buffer, yy_endRead, 
+                                            yy_buffer.length-yy_endRead);
+
+    if ( numRead == -1 ) return YYEOF;
+
+    yy_endRead+= numRead;
+
+    return yy_buffer[yy_currentPos++];
+  }
+
+    
+  /**
+   * Closes the input stream.
+   */
+  final public void yyclose() throws java.io.IOException {
+    yy_atEOF = true;            /* indicate end of file */
+    yy_endRead = yy_startRead;  /* invalidate buffer    */
+    yy_reader.close();
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  final public int yystate() {
+    return yy_lexical_state;
+  }
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  final public void yybegin(int newState) {
+    yy_lexical_state = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  final public String yytext() {
+    return new String( yy_buffer, yy_startRead, yy_markedPos-yy_startRead );
+  }
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  final public int yylength() {
+    return yy_markedPos-yy_startRead;
+  }
+
+
+  /**
+   * Reports an error that occured while scanning - from the SED JFlex skeleton
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void yy_ScanError(int errorCode) {
+    try {
+      Logger.log(Logger.ERROR, YY_ERROR_MSG[errorCode]);
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      Logger.log(Logger.ERROR, YY_ERROR_MSG[YY_UNKNOWN_ERROR]);
+    }
+    // DO NOT EXIT the VM on an error
+    // System.exit(1);
+  } 
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+  void yypushback(int number) {
+    if ( number > yylength() )
+      yy_ScanError(YY_PUSHBACK_2BIG);
+
+    yy_markedPos -= number;
+  }
+
+	/**
+	 * user method - skeleton.sed
+	 */
+	protected final boolean containsTagName(char[] markerTagName, int offset, int tagnameLength) {
+		for(int j = 0; j < fBlockMarkers.size(); j++) {
+			BlockMarker marker = (BlockMarker)fBlockMarkers.get(j);
+			if(marker.getTagName().length() == tagnameLength) {
+				boolean matchesSoFar = true;
+				for(int i = 0; i < tagnameLength && matchesSoFar; i++) {
+					if(marker.isCaseSensitive()) {
+						if(marker.getTagName().charAt(i) != markerTagName[i + offset])
+							matchesSoFar = false;
+					}
+					else {
+						if(Character.toLowerCase(marker.getTagName().charAt(i)) != Character.toLowerCase(markerTagName[i + offset]))
+							matchesSoFar = false;
+					}
+				}
+				if(matchesSoFar)
+					return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * user method - skeleton.sed
+	 *
+	 * Return ALL of the regions scannable within the remaining text
+	 * Note: for verification use
+	 */
+	public final List getRegions() {
+		List tokens = new ArrayList();
+		ITextRegion region = null;
+		try {
+			region = getNextToken();
+			while(region != null) {
+				if (region != null) {
+					tokens.add(region);
+				}
+				region = getNextToken();
+			}
+		}
+		catch (StackOverflowError e) {
+			Logger.logException(getClass().getName()+": input could not be tokenized correctly at position " + getOffset(), e);//$NON-NLS-1$
+			throw e;
+		}
+		catch (Exception e) {
+			// Since this is convenience method and NOT the recommended 
+			// way of getting tokens, many errors are simply hidden
+			Logger.logException("Exception not handled retrieving regions: " + e.getLocalizedMessage(), e);//$NON-NLS-1$
+		}
+		return tokens;
+	}
+	/**
+	 * user method - skeleton.sed
+	 */
+	private final void dump(String s) {
+		if (Debug.debugTokenizer) {
+			System.out.println(s + " (" + yychar + "-" + //$NON-NLS-2$//$NON-NLS-1$
+				(yylength() + yychar) + "):\'" +//$NON-NLS-1$
+					StringUtils.escape(yytext()) + "\'");//$NON-NLS-1$
+		}
+	}
+	/* user method  - skeleton.sed */
+	public final boolean isEOF() {
+		return yy_atEOF;
+	}
+/* user method - skeleton.sed */
+protected final boolean containsTagName(String markerTagName) {
+	Iterator blocks = fBlockMarkers.iterator();
+	while(blocks.hasNext()) {
+		BlockMarker marker = (BlockMarker)blocks.next();
+		if(marker.isCaseSensitive()) {
+			if(marker.getTagName().equals(markerTagName))
+				return true;
+		}
+		else {
+			if(marker.getTagName().equalsIgnoreCase(markerTagName))
+				return true;
+		}
+	}
+	return false;
+}
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void yy_do_eof() {
+    if (!yy_eof_done) {
+      yy_eof_done = true;
+    // do nothing, this is the downstream parser's job
+
+    }
+  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  public String primGetNextToken() throws java.io.IOException {
+    int yy_input;
+    int yy_action;
+
+    yy_pushbackPos = -1;
+    boolean yy_was_pushback;
+
+    while (true) {
+
+      yychar+= yylength();
+
+      boolean yy_counted = false;
+      for (yy_currentPos = yy_startRead; yy_currentPos < yy_markedPos;
+                                                      yy_currentPos++) {
+        switch (yy_buffer[yy_currentPos]) {
+        case '\r':
+          yyline++;
+          yy_counted = true;
+          break;
+        case '\n':
+          if (yy_counted)
+            yy_counted = false;
+          else {
+            yyline++;
+          }
+          break;
+        default:
+          yy_counted = false;
+        }
+      }
+
+      if (yy_counted) {
+        if ( yy_advance() == '\n' ) yyline--;
+        if ( !yy_atEOF ) yy_currentPos--;
+      }
+
+      yy_action = -1;
+
+      yy_currentPos = yy_startRead = yy_markedPos;
+
+      yy_state = yy_lexical_state;
+
+      yy_was_pushback = false;
+
+      yy_forAction: {
+        while (true) {
+    
+          yy_input = yy_advance();
+
+          if ( yy_input == YYEOF ) break yy_forAction;
+
+          int yy_next = yytrans[ yy_rowMap[yy_state] + yycmap[yy_input] ];
+          if (yy_next == -1) break yy_forAction;
+          yy_state = yy_next;
+
+          int yy_attributes = YY_ATTRIBUTE[yy_state];
+          if ( (yy_attributes & 2) > 0 )
+            yy_pushbackPos = yy_currentPos;
+
+          if ( (yy_attributes & 1) > 0 ) {
+            yy_was_pushback = (yy_attributes & 4) > 0;
+            yy_action = yy_state; 
+            yy_markedPos = yy_currentPos; 
+            if ( (yy_attributes & 8) > 0 ) break yy_forAction;
+          }
+
+        }
+      }
+
+      if (yy_was_pushback)
+        yy_markedPos = yy_pushbackPos;
+
+      switch (yy_action) {    
+
+        case 622: 
+        case 627: 
+        case 634: 
+        case 639: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("jsp directive tag name");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+        return JSP_DIRECTIVE_NAME;
+ }
+        case 655: break;
+        case 597: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XSL processing instruction target");//$NON-NLS-1$
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 656: break;
+        case 580: 
+        case 583: 
+        case 584: 
+        case 585: 
+        case 586: 
+        case 587: 
+        case 588: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nCDATA start");//$NON-NLS-1$
+	fStateStack.push(yystate());
+	yybegin(ST_CDATA_TEXT);
+	return XML_CDATA_OPEN;
+ }
+        case 657: break;
+        case 572: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("jsp:root tag name");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+        return JSP_ROOT_TAG_NAME;
+ }
+        case 658: break;
+        case 563: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("element");//$NON-NLS-1$
+	yybegin(ST_XML_ELEMENT_DECLARATION);
+	return XML_ELEMENT_DECLARATION;
+ }
+        case 659: break;
+        case 562: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist");//$NON-NLS-1$
+	yybegin(ST_XML_ATTLIST_DECLARATION);
+	return XML_ATTLIST_DECLARATION;
+ }
+        case 660: break;
+        case 561: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_DECLARATION);
+	return XML_DOCTYPE_DECLARATION;
+ }
+        case 661: break;
+        case 546: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype external id");//$NON-NLS-1$
+	fEmbeddedHint = XML_DOCTYPE_EXTERNAL_ID_PUBREF;
+	yybegin(ST_XML_DOCTYPE_ID_PUBLIC);
+	return XML_DOCTYPE_EXTERNAL_ID_PUBLIC;
+ }
+        case 662: break;
+        case 545: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype external id");//$NON-NLS-1$
+	fEmbeddedHint = XML_DOCTYPE_EXTERNAL_ID_SYSREF;
+	yybegin(ST_XML_DOCTYPE_ID_SYSTEM);
+	return XML_DOCTYPE_EXTERNAL_ID_SYSTEM;
+ }
+        case 663: break;
+        case 539: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction target");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_DHTML_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 664: break;
+        case 514: 
+        case 555: 
+        case 556: 
+          { 
+	return JSP_VBL_QUOTED_CONTENT;
+ }
+        case 665: break;
+        case 504: 
+        case 551: 
+        case 552: 
+          { 
+	return JSP_EL_QUOTED_CONTENT;
+ }
+        case 666: break;
+        case 496: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nJSP comment close");//$NON-NLS-1$
+	yybegin(YYINITIAL);
+	return JSP_COMMENT_CLOSE;
+ }
+        case 667: break;
+        case 483: 
+          { 
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint);//$NON-NLS-1$
+	}
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	fStateStack.push(yystate());
+	if(yylength() > 2)
+		yypushback(yylength() -2);
+	if(Debug.debugTokenizer)
+		dump("VBL in attr value");//$NON-NLS-1$
+	yybegin(ST_JSP_VBL);
+	fELlevel++;
+	assembleEmbeddedContainer(JSP_VBL_OPEN, new String[]{JSP_VBL_CLOSE});
+	fStateStack.pop();
+	yybegin(ST_XML_ATTRIBUTE_NAME);
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+	return PROXY_CONTEXT;
+ }
+        case 668: break;
+        case 482: 
+          { 
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint);//$NON-NLS-1$
+	}
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	fStateStack.push(yystate());
+	if(yylength() > 2)
+		yypushback(yylength() -2);
+	if(Debug.debugTokenizer)
+		dump("EL in attr value");//$NON-NLS-1$
+	yybegin(ST_JSP_EL);
+	fELlevel++;
+	assembleEmbeddedContainer(JSP_EL_OPEN, new String[]{JSP_EL_CLOSE});
+	fStateStack.pop();
+	yybegin(ST_XML_ATTRIBUTE_NAME);
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+	return PROXY_CONTEXT;
+ }
+        case 669: break;
+        case 476: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nCharRef");//$NON-NLS-1$
+	return XML_CHAR_REFERENCE;
+ }
+        case 670: break;
+        case 473: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\ncomment start");//$NON-NLS-1$
+	fEmbeddedHint = XML_COMMENT_TEXT;
+	fEmbeddedPostState = ST_XML_COMMENT;
+	yybegin(ST_XML_COMMENT);
+	return XML_COMMENT_OPEN;
+ }
+        case 671: break;
+        case 472: 
+        case 491: 
+        case 494: 
+        case 497: 
+        case 498: 
+        case 500: 
+        case 502: 
+        case 505: 
+        case 507: 
+        case 508: 
+        case 510: 
+        case 512: 
+        case 515: 
+          { 
+	/* JSP comment begun (anywhere)
+	 * A consequence of the start anywhere possibility is that the
+	 *  incoming state must be checked to see if it's erroneous
+	 *  due to the order of precedence generated
+	 */
+	// begin sanity checks
+	if(yystate() == ST_JSP_CONTENT) {
+		// at the beginning?!
+		yypushback(3);
+		return JSP_CONTENT;
+	}
+	else if(yystate() == ST_BLOCK_TAG_SCAN) {
+		yypushback(4);
+		return doBlockTagScan();
+	}
+	else if(yystate() == ST_XML_COMMENT) {
+		yypushback(4);
+		return scanXMLCommentText();
+	}
+	else if(yystate() == ST_JSP_COMMENT) {
+		yypushback(4);
+		return scanJSPCommentText();
+	}
+	else if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN)  {
+		yybegin(ST_JSP_COMMENT);
+		assembleEmbeddedContainer(JSP_COMMENT_OPEN, JSP_COMMENT_CLOSE);
+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN)
+			yybegin(ST_BLOCK_TAG_SCAN);
+		return PROXY_CONTEXT;
+	}
+	// finished sanity checks
+	if(yystate()==YYINITIAL) {
+		// the simple case, just a regular scriptlet out in content
+		if(Debug.debugTokenizer)
+			dump("\nJSP comment start");//$NON-NLS-1$
+		yybegin(ST_JSP_COMMENT);
+		return JSP_COMMENT_OPEN;
+	}
+	else {
+		if (Debug.debugTokenizer) {
+			System.out.println("begin embedded region: " + fEmbeddedHint);//$NON-NLS-1$
+		}
+		if(Debug.debugTokenizer)
+			dump("JSP comment start");//$NON-NLS-1$
+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;
+		else if(yystate() == ST_CDATA_TEXT) {
+			fEmbeddedPostState = ST_CDATA_TEXT;
+			fEmbeddedHint = XML_CDATA_TEXT;
+		}
+		yybegin(ST_JSP_COMMENT);
+		// the comment container itself will act as comment text
+		fEmbeddedHint = JSP_COMMENT_TEXT;
+		assembleEmbeddedContainer(JSP_COMMENT_OPEN, JSP_COMMENT_CLOSE);
+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {
+			yybegin(ST_BLOCK_TAG_SCAN);
+			return BLOCK_TEXT;
+		}
+		/*
+		 * required help for successive embedded regions; mark this one as a
+		 * comment so it will be otherwise ignored but preserved (which is why
+		 * we can't use white-space)
+		 */
+		if(yystate() == ST_XML_TAG_NAME) {
+			fEmbeddedHint = XML_TAG_NAME;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+			fEmbeddedPostState = ST_XML_EQUALS;
+		}
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		return PROXY_CONTEXT;
+	}
+ }
+        case 672: break;
+        case 381: 
+        case 382: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction target");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 673: break;
+        case 380: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("comment end");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+	yybegin(YYINITIAL);
+	return XML_COMMENT_CLOSE;
+ }
+        case 674: break;
+        case 379: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("CDATA end");//$NON-NLS-1$
+	yybegin(fStateStack.pop());
+	return XML_CDATA_CLOSE;
+ }
+        case 675: break;
+        case 378: 
+          { 
+	yybegin(ST_JSP_VBL);
+	if(yylength() > 2)
+		yypushback(yylength() - 2);
+	fELlevel++;
+	fEmbeddedHint = XML_CONTENT;
+	fEmbeddedPostState = YYINITIAL;
+	assembleEmbeddedContainer(JSP_VBL_OPEN, JSP_VBL_CLOSE);
+	fEmbeddedHint = XML_CONTENT;
+	yybegin(YYINITIAL);
+	return PROXY_CONTEXT;
+ }
+        case 676: break;
+        case 377: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nPEReference");//$NON-NLS-1$
+	return XML_PE_REFERENCE;
+ }
+        case 677: break;
+        case 376: 
+          { 
+	yybegin(ST_JSP_EL);
+	if(yylength() > 2)
+		yypushback(yylength() - 2);
+	fELlevel++;
+	fEmbeddedHint = XML_CONTENT;
+	fEmbeddedPostState = YYINITIAL;
+	assembleEmbeddedContainer(JSP_EL_OPEN, JSP_EL_CLOSE);
+	fEmbeddedHint = XML_CONTENT;
+	yybegin(YYINITIAL);
+	return PROXY_CONTEXT;
+ }
+        case 678: break;
+        case 373: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nEntityRef");//$NON-NLS-1$
+	return XML_ENTITY_REFERENCE;
+ }
+        case 679: break;
+        case 367: 
+        case 407: 
+        case 415: 
+        case 422: 
+        case 427: 
+        case 432: 
+        case 437: 
+        case 443: 
+        case 449: 
+        case 453: 
+        case 458: 
+        case 463: 
+        case 469: 
+          { 
+	/* JSP expression begun (anywhere)
+	 * A consequence of the start anywhere possibility is that the
+	 *  incoming state must be checked to see if it's erroneous
+	 *  due to the order of precedence generated
+	 */
+	// begin sanity checks
+	if(yystate() == ST_JSP_CONTENT) {
+		// at the beginning?!
+		yypushback(2);
+		return JSP_CONTENT;
+	}
+	else if(yystate() == ST_BLOCK_TAG_SCAN) {
+		yypushback(3);
+		return doBlockTagScan();
+	}
+	else if(yystate() == ST_XML_COMMENT) {
+		yypushback(3);
+		return scanXMLCommentText();
+	}
+	else if(yystate() == ST_JSP_COMMENT) {
+		yypushback(3);
+		return scanJSPCommentText();
+	}
+	// end sanity checks
+	fStateStack.push(yystate());
+	if(fStateStack.peek()==YYINITIAL) {
+		// the simple case, just an expression out in content
+		if(Debug.debugTokenizer)
+			dump("\nJSP expression start");//$NON-NLS-1$
+		yybegin(ST_JSP_CONTENT);
+		return JSP_EXPRESSION_OPEN;
+	}
+	else {
+		if (Debug.debugTokenizer) {
+			System.out.println("begin embedded region: " + fEmbeddedHint);//$NON-NLS-1$
+		}
+		if(Debug.debugTokenizer)
+			dump("JSP expression start");//$NON-NLS-1$
+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;
+		else if(yystate() == ST_CDATA_TEXT) {
+			fEmbeddedPostState = ST_CDATA_TEXT;
+			fEmbeddedHint = XML_CDATA_TEXT;
+		}
+		yybegin(ST_JSP_CONTENT);
+		assembleEmbeddedContainer(JSP_EXPRESSION_OPEN, JSP_CLOSE);
+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {
+			yybegin(ST_BLOCK_TAG_SCAN);
+			return BLOCK_TEXT;
+		}
+		// required help for successive embedded regions
+		if(yystate() == ST_XML_TAG_NAME) {
+			fEmbeddedHint = XML_TAG_NAME;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+			fEmbeddedPostState = ST_XML_EQUALS;
+		}
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		return PROXY_CONTEXT;
+	}
+ }
+        case 680: break;
+        case 366: 
+        case 406: 
+        case 414: 
+        case 421: 
+        case 426: 
+        case 431: 
+        case 436: 
+        case 442: 
+        case 448: 
+        case 452: 
+        case 457: 
+        case 462: 
+        case 468: 
+          { 
+	/* JSP declaration begun (anywhere)
+	 * A consequence of the start anywhere possibility is that the
+	 *  incoming state must be checked to see if it's erroneous
+	 *  due to the order of precedence generated
+	 */
+	// begin sanity checks
+	if(yystate() == ST_JSP_CONTENT) {
+		// at the beginning?!
+		yypushback(2);
+		return JSP_CONTENT;
+	}
+	else if(yystate() == ST_BLOCK_TAG_SCAN) {
+		yypushback(3);
+		return doBlockTagScan();
+	}
+	else if(yystate() == ST_XML_COMMENT) {
+		yypushback(3);
+		return scanXMLCommentText();
+	}
+	else if(yystate() == ST_JSP_COMMENT) {
+		yypushback(3);
+		return scanJSPCommentText();
+	}
+	// end sanity checks
+	fStateStack.push(yystate());
+	if(fStateStack.peek()==YYINITIAL) {
+		// the simple case, just a declaration out in content
+		if(Debug.debugTokenizer)
+			dump("\nJSP declaration start");//$NON-NLS-1$
+		yybegin(ST_JSP_CONTENT);
+		return JSP_DECLARATION_OPEN;
+	}
+	else {
+		if (Debug.debugTokenizer) {
+			System.out.println("begin embedded region: " + fEmbeddedHint);//$NON-NLS-1$
+		}
+		if(Debug.debugTokenizer)
+			dump("JSP declaration start");//$NON-NLS-1$
+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;
+		else if(yystate() == ST_CDATA_TEXT) {
+			fEmbeddedPostState = ST_CDATA_TEXT;
+			fEmbeddedHint = XML_CDATA_TEXT;
+		}
+		yybegin(ST_JSP_CONTENT);
+		assembleEmbeddedContainer(JSP_DECLARATION_OPEN, JSP_CLOSE);
+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {
+			yybegin(ST_BLOCK_TAG_SCAN);
+			return BLOCK_TEXT;
+		}
+		// required help for successive embedded regions
+		if(yystate() == ST_XML_TAG_NAME) {
+			fEmbeddedHint = XML_TAG_NAME;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+			fEmbeddedPostState = ST_XML_EQUALS;
+		}
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		return PROXY_CONTEXT;
+	}
+ }
+        case 681: break;
+        case 365: 
+        case 405: 
+        case 413: 
+        case 420: 
+        case 425: 
+        case 430: 
+        case 435: 
+        case 441: 
+        case 447: 
+        case 451: 
+        case 456: 
+        case 461: 
+        case 467: 
+          { 
+	/* JSP directive begun (anywhere)
+	 * A consequence of the start anywhere possibility is that the
+	 *  incoming state must be checked to see if it's erroneous
+	 *  due to the order of precedence generated
+	 */
+	// begin sanity checks
+	if(yystate() == ST_JSP_CONTENT) {
+		// at the beginning?!
+		yypushback(2);
+		return JSP_CONTENT;
+	}
+	else if(yystate() == ST_BLOCK_TAG_SCAN) {
+		yypushback(3);
+		return doBlockTagScan();
+	}
+	else if(yystate() == ST_XML_COMMENT) {
+		yypushback(3);
+		return scanXMLCommentText();
+	}
+	else if(yystate() == ST_JSP_COMMENT) {
+		yypushback(3);
+		return scanJSPCommentText();
+	}
+	// end sanity checks
+	fStateStack.push(yystate());
+	if(fStateStack.peek()==YYINITIAL) {
+		// the simple case, just a declaration out in content
+		if(Debug.debugTokenizer)
+			dump("\nJSP directive start");//$NON-NLS-1$
+		yybegin(ST_JSP_DIRECTIVE_NAME);
+		return JSP_DIRECTIVE_OPEN;
+	}
+	else {
+		if (Debug.debugTokenizer) {
+			System.out.println("begin embedded region: " + fEmbeddedHint);//$NON-NLS-1$
+		}
+		if(Debug.debugTokenizer)
+			dump("JSP declaration start");//$NON-NLS-1$
+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;
+		else if(yystate() == ST_CDATA_TEXT) {
+			fEmbeddedPostState = ST_CDATA_TEXT;
+			fEmbeddedHint = XML_CDATA_TEXT;
+		}
+		yybegin(ST_JSP_DIRECTIVE_NAME);
+		assembleEmbeddedContainer(JSP_DIRECTIVE_OPEN, new String[]{JSP_DIRECTIVE_CLOSE, JSP_CLOSE});
+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {
+			yybegin(ST_BLOCK_TAG_SCAN);
+			return BLOCK_TEXT;
+		}
+		// required help for successive embedded regions
+		if(yystate() == ST_XML_TAG_NAME) {
+			fEmbeddedHint = XML_TAG_NAME;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+			fEmbeddedPostState = ST_XML_EQUALS;
+		}
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		return PROXY_CONTEXT;
+	}
+ }
+        case 682: break;
+        case 355: 
+          { 
+	yybegin(ST_JSP_VBL_DQUOTES_END);
+	return JSP_VBL_QUOTED_CONTENT;
+ }
+        case 683: break;
+        case 351: 
+          { 
+	yybegin(ST_JSP_VBL_SQUOTES_END);
+	return JSP_VBL_QUOTED_CONTENT;
+ }
+        case 684: break;
+        case 349: 
+          { 
+	fELlevel++;
+	if(fELlevel == 1) {
+		return JSP_VBL_OPEN;
+	}
+ }
+        case 685: break;
+        case 339: 
+          { 
+	yybegin(ST_JSP_EL_DQUOTES_END);
+	return JSP_EL_QUOTED_CONTENT;
+ }
+        case 686: break;
+        case 335: 
+          { 
+	yybegin(ST_JSP_EL_SQUOTES_END);
+	return JSP_EL_QUOTED_CONTENT;
+ }
+        case 687: break;
+        case 333: 
+          { 
+	//System.out.println(JSP_EL_CONTENT+ ":[" + yytext() + "]");
+	return JSP_EL_CONTENT;
+ }
+        case 688: break;
+        case 332: 
+          { 
+	fELlevel++;
+	if(fELlevel == 1) {
+		return JSP_EL_OPEN;
+	}
+ }
+        case 689: break;
+        case 329: 
+          { 
+	int enterState = yystate();
+	yybegin(ST_JSP_DQUOTED_VBL);
+	assembleEmbeddedContainer(JSP_VBL_OPEN, new String[]{JSP_VBL_CLOSE, XML_TAG_ATTRIBUTE_VALUE_DQUOTE});
+	// abort early when an unescaped double quote is found in the VBL
+	if(fEmbeddedContainer.getLastRegion().getType().equals(XML_TAG_ATTRIBUTE_VALUE_DQUOTE)) {
+		yybegin(ST_ABORT_EMBEDDED);
+		fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	}
+	else {
+		yybegin(enterState);
+	}
+	return PROXY_CONTEXT;
+ }
+        case 690: break;
+        case 328: 
+          { 
+	int enterState = yystate();
+	yybegin(ST_JSP_DQUOTED_EL);
+	assembleEmbeddedContainer(JSP_EL_OPEN, new String[]{JSP_EL_CLOSE, XML_TAG_ATTRIBUTE_VALUE_DQUOTE});
+	// abort early when an unescaped double quote is found in the EL
+	if(fEmbeddedContainer.getLastRegion().getType().equals(XML_TAG_ATTRIBUTE_VALUE_DQUOTE)) {
+		yybegin(ST_ABORT_EMBEDDED);
+		fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	}
+	else {
+		yybegin(enterState);
+	}
+	return PROXY_CONTEXT;
+ }
+        case 691: break;
+        case 326: 
+          { 
+	int enterState = yystate();
+	yybegin(ST_JSP_SQUOTED_VBL);
+	assembleEmbeddedContainer(JSP_VBL_OPEN, new String[]{JSP_VBL_CLOSE, XML_TAG_ATTRIBUTE_VALUE_SQUOTE});
+	// abort early when an unescaped single quote is found in the VBL
+	if(fEmbeddedContainer.getLastRegion().getType().equals(XML_TAG_ATTRIBUTE_VALUE_SQUOTE)) {
+		yybegin(ST_ABORT_EMBEDDED);
+		fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	}
+	else {
+		yybegin(enterState);
+	}
+	return PROXY_CONTEXT;
+ }
+        case 692: break;
+        case 325: 
+          { 
+	int enterState = yystate();
+	yybegin(ST_JSP_SQUOTED_EL);
+	assembleEmbeddedContainer(JSP_EL_OPEN, new String[]{JSP_EL_CLOSE, XML_TAG_ATTRIBUTE_VALUE_SQUOTE});
+	// abort early when an unescaped single quote is found in the EL
+	if(fEmbeddedContainer.getLastRegion().getType().equals(XML_TAG_ATTRIBUTE_VALUE_SQUOTE)) {
+		yybegin(ST_ABORT_EMBEDDED);
+		fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	}
+	else {
+		yybegin(enterState);
+	}
+	return PROXY_CONTEXT;
+ }
+        case 693: break;
+        case 324: 
+          { 
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint);//$NON-NLS-1$
+	}
+	int incomingState = yystate();
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	if(Debug.debugTokenizer)
+		dump("JSP attribute value start - end tag");//$NON-NLS-1$
+	yybegin(ST_XML_TAG_NAME);
+	assembleEmbeddedContainer(XML_END_TAG_OPEN, new String[]{XML_TAG_CLOSE,XML_EMPTY_TAG_CLOSE});
+	if(yystate() != ST_ABORT_EMBEDDED)
+        yybegin(incomingState);
+	return PROXY_CONTEXT;
+ }
+        case 694: break;
+        case 283: 
+        case 295: 
+        case 301: 
+          { 
+	return XML_DOCTYPE_INTERNAL_SUBSET;
+ }
+        case 695: break;
+        case 271: 
+          { 
+	String tagName = yytext().substring(1);
+	// pushback to just after the opening bracket
+	yypushback(yylength() - 1);
+	/*
+	 * If this tag can not be nested or we're already searching for an
+	 * attribute name, equals, or value, return immediately.
+	 */
+	if (!isNestable(tagName) || (!fStateStack.empty() && (fStateStack.peek() == ST_XML_ATTRIBUTE_NAME || fStateStack.peek() == ST_XML_EQUALS || fStateStack.peek() == ST_XML_ATTRIBUTE_VALUE))) {
+		yybegin(ST_XML_TAG_NAME);
+		return XML_TAG_OPEN;
+	}
+	if(Debug.debugTokenizer)
+		dump("tag in place of attr value");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	fStateStack.push(yystate());
+	// embedded container should be looking for the name (again) next
+	yybegin(ST_XML_TAG_NAME);
+	assembleEmbeddedTagSequence(XML_TAG_OPEN, tagName); // ?
+	fStateStack.pop();
+	yybegin(ST_XML_ATTRIBUTE_NAME);
+	return PROXY_CONTEXT;
+ }
+        case 696: break;
+        case 269: 
+          { 
+	String tagName = yytext().substring(1);
+	// pushback to just after the opening bracket
+	yypushback(yylength() - 1);
+	/*
+	 * If this tag can not be nested or we're already searching for an
+	 * attribute name, equals, or value, return immediately.
+	 */
+	if (!isNestable(tagName) || (!fStateStack.empty() && (fStateStack.peek() == ST_XML_ATTRIBUTE_NAME || fStateStack.peek() == ST_XML_EQUALS || fStateStack.peek() == ST_XML_ATTRIBUTE_VALUE))) {
+		yybegin(ST_XML_TAG_NAME);
+		return XML_TAG_OPEN;
+	}
+	if(Debug.debugTokenizer)
+		dump("tag in place of attr name");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	fStateStack.push(yystate());
+	// embedded container should be looking for the name (again) next
+	yybegin(ST_XML_TAG_NAME);
+	assembleEmbeddedTagSequence(XML_TAG_OPEN, tagName); // ?
+	fStateStack.pop();
+	yybegin(ST_XML_EQUALS);
+	return PROXY_CONTEXT;
+ }
+        case 697: break;
+        case 267: 
+          { 
+        yybegin(YYINITIAL);
+	fEmbeddedHint = UNDEFINED;
+	if(Debug.debugTokenizer)
+		dump("empty tag close");//$NON-NLS-1$
+        return XML_EMPTY_TAG_CLOSE;
+ }
+        case 698: break;
+        case 125: 
+          { 
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint);//$NON-NLS-1$
+	}
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;
+	yybegin(ST_XML_ATTRIBUTE_VALUE_DQUOTED);
+	fStateStack.push(yystate());
+	if(Debug.debugTokenizer)
+		dump("JSP attribute value start - complex double quoted");//$NON-NLS-1$
+	assembleEmbeddedContainer(XML_TAG_ATTRIBUTE_VALUE_DQUOTE, XML_TAG_ATTRIBUTE_VALUE_DQUOTE);
+	fStateStack.pop();
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+	yybegin(ST_XML_ATTRIBUTE_NAME);
+	return PROXY_CONTEXT;
+ }
+        case 699: break;
+        case 123: 
+          { 
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint);//$NON-NLS-1$
+	}
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	fStateStack.push(yystate());
+	if(Debug.debugTokenizer)
+		dump("JSP tag embedded name start - start tag");//$NON-NLS-1$
+	yybegin(ST_XML_TAG_NAME);
+	assembleEmbeddedContainer(XML_TAG_OPEN, new String[]{XML_TAG_CLOSE,XML_EMPTY_TAG_CLOSE});
+	fStateStack.pop();
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+	return PROXY_CONTEXT;
+ }
+        case 700: break;
+        case 122: 
+        case 127: 
+        case 128: 
+        case 273: 
+        case 277: 
+        case 278: 
+        case 387: 
+        case 390: 
+        case 481: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attr value");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 701: break;
+        case 121: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("equals");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+        yybegin(ST_XML_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 702: break;
+        case 120: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attr name");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+        yybegin(ST_XML_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 703: break;
+        case 116: 
+        case 117: 
+        case 118: 
+        case 268: 
+        case 386: 
+        case 480: 
+        case 520: 
+        case 521: 
+        case 540: 
+        case 541: 
+        case 559: 
+        case 560: 
+        case 573: 
+        case 582: 
+        case 590: 
+        case 592: 
+        case 594: 
+        case 596: 
+        case 599: 
+        case 605: 
+        case 606: 
+        case 607: 
+        case 608: 
+        case 609: 
+        case 615: 
+        case 616: 
+        case 617: 
+        case 618: 
+        case 619: 
+        case 625: 
+        case 626: 
+        case 628: 
+        case 629: 
+        case 635: 
+        case 636: 
+        case 637: 
+        case 638: 
+        case 644: 
+        case 645: 
+        case 646: 
+        case 647: 
+        case 650: 
+        case 651: 
+        case 653: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("tag name");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 704: break;
+        case 114: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("tag close");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+	if(isBlockMarker()) {
+		fEmbeddedHint = getBlockMarkerContext();
+		fEmbeddedPostState = ST_BLOCK_TAG_SCAN;
+        	yybegin(ST_BLOCK_TAG_SCAN);
+	}
+	else
+        	yybegin(YYINITIAL);
+        return XML_TAG_CLOSE;
+ }
+        case 705: break;
+        case 107: 
+        case 111: 
+        case 263: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attr value");//$NON-NLS-1$
+        yybegin(ST_JSP_DIRECTIVE_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 706: break;
+        case 106: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("equals");//$NON-NLS-1$
+        yybegin(ST_JSP_DIRECTIVE_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 707: break;
+        case 105: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attr name");//$NON-NLS-1$
+        yybegin(ST_JSP_DIRECTIVE_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 708: break;
+        case 102: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("JSP directive name");//$NON-NLS-1$
+	yybegin(ST_JSP_DIRECTIVE_NAME_WHITESPACE);
+	return JSP_DIRECTIVE_NAME;
+ }
+        case 709: break;
+        case 98: 
+        case 99: 
+        case 100: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("JSP code content");//$NON-NLS-1$
+	return doScan("%>", false, false, false, JSP_CONTENT, ST_JSP_CONTENT, ST_JSP_CONTENT);
+ }
+        case 710: break;
+        case 94: 
+        case 96: 
+        case 97: 
+        case 253: 
+        case 254: 
+        case 257: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction attribute value");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_DHTML_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 711: break;
+        case 93: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction '='");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+        yybegin(ST_DHTML_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 712: break;
+        case 92: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction attribute name");//$NON-NLS-1$
+        yybegin(ST_DHTML_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 713: break;
+        case 90: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction end");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 714: break;
+        case 84: 
+        case 86: 
+        case 244: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction attribute value");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 715: break;
+        case 83: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction '='");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+        yybegin(ST_XML_PI_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 716: break;
+        case 49: 
+        case 199: 
+        case 200: 
+        case 203: 
+        case 213: 
+        case 214: 
+        case 217: 
+        case 218: 
+        case 360: 
+        case 363: 
+        case 446: 
+        case 460: 
+        case 466: 
+          { 
+	return JSP_VBL_CONTENT;
+ }
+        case 717: break;
+        case 42: 
+        case 178: 
+        case 179: 
+        case 182: 
+        case 192: 
+        case 193: 
+        case 196: 
+        case 197: 
+        case 330: 
+        case 344: 
+        case 347: 
+        case 418: 
+        case 419: 
+        case 434: 
+        case 440: 
+          { 
+	return JSP_EL_CONTENT;
+ }
+        case 718: break;
+        case 35: 
+        case 159: 
+        case 160: 
+        case 321: 
+        case 412: 
+        case 416: 
+        case 495: 
+        case 528: 
+        case 548: 
+        case 565: 
+        case 575: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist contentspec");//$NON-NLS-1$
+	return XML_ATTLIST_DECL_CONTENT;
+ }
+        case 719: break;
+        case 33: 
+        case 152: 
+        case 153: 
+        case 311: 
+        case 404: 
+        case 408: 
+        case 492: 
+        case 527: 
+        case 547: 
+        case 564: 
+        case 574: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("elementdecl contentspec");//$NON-NLS-1$
+	return XML_ELEMENT_DECL_CONTENT;
+ }
+        case 720: break;
+        case 22: 
+        case 112: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("inappropriate tag name");//$NON-NLS-1$
+	if(!fStateStack.empty() && (fStateStack.peek()==ST_XML_ATTRIBUTE_VALUE_SQUOTED||fStateStack.peek()==ST_XML_ATTRIBUTE_VALUE_DQUOTED)) {
+		yybegin(ST_ABORT_EMBEDDED);
+		yypushback(yylength()-1);
+		return XML_TAG_ATTRIBUTE_VALUE;
+	}
+	yybegin(YYINITIAL);
+        return XML_CONTENT;
+ }
+        case 721: break;
+        case 18: 
+        case 104: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("white space");//$NON-NLS-1$
+	yybegin(ST_JSP_DIRECTIVE_ATTRIBUTE_NAME);
+	return WHITE_SPACE;
+ }
+        case 722: break;
+        case 5: 
+        case 8: 
+        case 9: 
+        case 10: 
+        case 12: 
+        case 13: 
+        case 14: 
+        case 15: 
+        case 17: 
+        case 19: 
+        case 20: 
+        case 21: 
+        case 23: 
+        case 24: 
+        case 25: 
+        case 26: 
+        case 27: 
+        case 28: 
+        case 29: 
+        case 30: 
+        case 31: 
+        case 32: 
+        case 34: 
+        case 40: 
+        case 41: 
+        case 72: 
+        case 169: 
+        case 174: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("white space");//$NON-NLS-1$
+        return WHITE_SPACE;
+ }
+        case 723: break;
+        case 0: 
+        case 56: 
+        case 59: 
+        case 61: 
+        case 225: 
+        case 227: 
+        case 228: 
+        case 230: 
+        case 232: 
+        case 370: 
+        case 371: 
+        case 372: 
+        case 475: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nXML content");//$NON-NLS-1$
+	return XML_CONTENT;
+ }
+        case 724: break;
+        case 57: 
+        case 101: 
+        case 113: 
+        case 119: 
+        case 129: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nstart tag open");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_NAME;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+        yybegin(ST_XML_TAG_NAME);
+        return XML_TAG_OPEN;
+ }
+        case 725: break;
+        case 58: 
+        case 60: 
+        case 64: 
+        case 65: 
+        case 66: 
+        case 70: 
+        case 71: 
+        case 81: 
+        case 85: 
+        case 87: 
+        case 88: 
+        case 89: 
+        case 91: 
+        case 95: 
+        case 103: 
+        case 108: 
+        case 109: 
+        case 110: 
+        case 115: 
+        case 124: 
+        case 131: 
+        case 132: 
+        case 133: 
+        case 134: 
+        case 136: 
+        case 137: 
+        case 139: 
+        case 140: 
+        case 141: 
+        case 144: 
+        case 145: 
+        case 146: 
+        case 149: 
+        case 150: 
+        case 151: 
+        case 156: 
+        case 157: 
+        case 158: 
+        case 166: 
+        case 171: 
+        case 172: 
+        case 176: 
+        case 177: 
+        case 184: 
+        case 185: 
+        case 187: 
+        case 188: 
+        case 194: 
+        case 198: 
+        case 205: 
+        case 206: 
+        case 208: 
+        case 209: 
+        case 215: 
+        case 219: 
+          { 
+	if (Debug.debugTokenizer)
+		System.out.println("!!!unexpected!!!: \"" + yytext() + "\":" + //$NON-NLS-2$//$NON-NLS-1$
+			yychar + "-" + (yychar + yylength()));//$NON-NLS-1$
+	return UNDEFINED;
+ }
+        case 726: break;
+        case 62: 
+        case 63: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("CDATA text");//$NON-NLS-1$
+	fEmbeddedPostState = ST_CDATA_TEXT;
+	fEmbeddedHint = XML_CDATA_TEXT;
+	String returnedContext = doScan("]]>", false, true, true, XML_CDATA_TEXT, ST_CDATA_END,  ST_CDATA_END);//$NON-NLS-1$
+	if(returnedContext == XML_CDATA_TEXT)
+		yybegin(ST_CDATA_END);
+	return returnedContext;
+ }
+        case 727: break;
+        case 67: 
+        case 186: 
+        case 189: 
+        case 207: 
+        case 210: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("LINE FEED");//$NON-NLS-1$
+	return WHITE_SPACE;
+ }
+        case 728: break;
+        case 68: 
+        case 69: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("comment content");//$NON-NLS-1$
+	return scanXMLCommentText();
+ }
+        case 729: break;
+        case 73: 
+        case 74: 
+        case 75: 
+        case 76: 
+        case 237: 
+        case 238: 
+        case 239: 
+        case 383: 
+        case 478: 
+        case 479: 
+        case 518: 
+        case 519: 
+        case 538: 
+        case 558: 
+        case 571: 
+        case 581: 
+        case 589: 
+        case 591: 
+        case 593: 
+        case 595: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("processing instruction target");//$NON-NLS-1$
+	fEmbeddedHint = XML_CONTENT;
+        yybegin(ST_PI_WS);
+        return XML_TAG_NAME;
+ }
+        case 730: break;
+        case 77: 
+          { 
+        yybegin(ST_PI_CONTENT);
+        return WHITE_SPACE;
+ }
+        case 731: break;
+        case 78: 
+        case 79: 
+        case 80: 
+          { 
+		// block scan until close is found
+	return doScan("?>", false, false, false, XML_PI_CONTENT, ST_XML_PI_TAG_CLOSE, ST_XML_PI_TAG_CLOSE);
+ }
+        case 732: break;
+        case 82: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction attribute name");//$NON-NLS-1$
+        yybegin(ST_XML_PI_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 733: break;
+        case 126: 
+          { 
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint);//$NON-NLS-1$
+	}
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;
+	yybegin(ST_XML_ATTRIBUTE_VALUE_SQUOTED);
+	fStateStack.push(yystate());
+	if(Debug.debugTokenizer)
+		dump("JSP attribute value start - complex single quoted");//$NON-NLS-1$
+	assembleEmbeddedContainer(XML_TAG_ATTRIBUTE_VALUE_SQUOTE, XML_TAG_ATTRIBUTE_VALUE_SQUOTE);
+	fStateStack.pop();
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+	fEmbeddedPostState = ST_XML_EQUALS;
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+	return PROXY_CONTEXT;
+ }
+        case 734: break;
+        case 130: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("declaration end");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return XML_DECLARATION_CLOSE;
+ }
+        case 735: break;
+        case 135: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype type");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_EXTERNAL_ID);
+	return XML_DOCTYPE_NAME;
+ }
+        case 736: break;
+        case 138: 
+        case 142: 
+        case 288: 
+        case 292: 
+        case 399: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype public reference");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+	fEmbeddedPostState = YYINITIAL;
+	yybegin(ST_XML_DOCTYPE_ID_SYSTEM);
+	return XML_DOCTYPE_EXTERNAL_ID_PUBREF;
+ }
+        case 737: break;
+        case 143: 
+        case 147: 
+        case 298: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype system reference");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+	fEmbeddedPostState = YYINITIAL;
+	yybegin(ST_XML_DECLARATION_CLOSE);
+	return XML_DOCTYPE_EXTERNAL_ID_SYSREF;
+ }
+        case 738: break;
+        case 148: 
+        case 304: 
+        case 308: 
+        case 402: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("elementdecl name");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+	fEmbeddedPostState = YYINITIAL;
+	yybegin(ST_XML_ELEMENT_DECLARATION_CONTENT);
+	return XML_ELEMENT_DECL_NAME;
+ }
+        case 739: break;
+        case 154: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("elementdecl close");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return XML_DECLARATION_CLOSE;
+ }
+        case 740: break;
+        case 155: 
+        case 314: 
+        case 318: 
+        case 410: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist name");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+	fEmbeddedPostState = YYINITIAL;
+	yybegin(ST_XML_ATTLIST_DECLARATION_CONTENT);
+	return XML_ATTLIST_DECL_NAME;
+ }
+        case 741: break;
+        case 161: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist close");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return XML_DECLARATION_CLOSE;
+ }
+        case 742: break;
+        case 164: 
+        case 165: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nJSP comment text");//$NON-NLS-1$
+	return scanJSPCommentText();
+ }
+        case 743: break;
+        case 167: 
+        case 173: 
+          { 
+	return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 744: break;
+        case 168: 
+          { 
+	if (Debug.debugTokenizer) {
+		System.out.println("begin embedded region: " + fEmbeddedHint);//$NON-NLS-1$
+	}
+	int incomingState = yystate();
+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+	if(Debug.debugTokenizer)
+		dump("tag inside of JSP attribute value start");//$NON-NLS-1$
+	yybegin(ST_XML_TAG_NAME);
+	assembleEmbeddedContainer(XML_TAG_OPEN, new String[]{XML_TAG_CLOSE,XML_EMPTY_TAG_CLOSE});
+	if(yystate() != ST_ABORT_EMBEDDED)
+        yybegin(incomingState);
+	return PROXY_CONTEXT;
+ }
+        case 745: break;
+        case 170: 
+          { 
+	return XML_TAG_ATTRIBUTE_VALUE_SQUOTE;
+ }
+        case 746: break;
+        case 175: 
+          { 
+	return XML_TAG_ATTRIBUTE_VALUE_DQUOTE;
+ }
+        case 747: break;
+        case 180: 
+          { 
+	yybegin(ST_JSP_EL_DQUOTES);
+	return JSP_EL_DQUOTE;
+ }
+        case 748: break;
+        case 181: 
+          { 
+	yybegin(ST_JSP_EL_SQUOTES);
+	return JSP_EL_SQUOTE;
+ }
+        case 749: break;
+        case 183: 
+          { 
+	fELlevel--;
+	if(fELlevel == 0) {
+		yybegin(YYINITIAL);
+		return JSP_EL_CLOSE;
+	}
+	return JSP_EL_CONTENT;
+ }
+        case 750: break;
+        case 190: 
+          { 
+	yybegin(ST_JSP_EL);
+	return JSP_EL_SQUOTE;
+ }
+        case 751: break;
+        case 191: 
+          { 
+	yybegin(ST_JSP_EL);
+	return JSP_EL_DQUOTE;
+ }
+        case 752: break;
+        case 195: 
+          { 
+	return JSP_EL_CLOSE;
+ }
+        case 753: break;
+        case 201: 
+          { 
+	yybegin(ST_JSP_VBL_DQUOTES);
+	return JSP_VBL_DQUOTE;
+ }
+        case 754: break;
+        case 202: 
+          { 
+	yybegin(ST_JSP_VBL_SQUOTES);
+	return JSP_VBL_SQUOTE;
+ }
+        case 755: break;
+        case 204: 
+          { 
+	fELlevel--;
+	if(fELlevel == 0) {
+		yybegin(YYINITIAL);
+		return JSP_VBL_CLOSE;
+	}
+	return JSP_VBL_CONTENT;
+ }
+        case 756: break;
+        case 211: 
+          { 
+	yybegin(ST_JSP_VBL);
+	return JSP_VBL_SQUOTE;
+ }
+        case 757: break;
+        case 212: 
+          { 
+	yybegin(ST_JSP_VBL);
+	return JSP_VBL_DQUOTE;
+ }
+        case 758: break;
+        case 216: 
+          { 
+	return JSP_VBL_CLOSE;
+ }
+        case 759: break;
+        case 220: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nend tag open");//$NON-NLS-1$
+	fEmbeddedHint = XML_TAG_NAME;
+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+        yybegin(ST_XML_TAG_NAME);
+        return XML_END_TAG_OPEN;
+ }
+        case 760: break;
+        case 221: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nprocessing instruction start");//$NON-NLS-1$
+	yybegin(ST_PI);
+        return XML_PI_OPEN;
+ }
+        case 761: break;
+        case 222: 
+        case 310: 
+        case 320: 
+        case 331: 
+        case 336: 
+        case 340: 
+        case 343: 
+        case 346: 
+        case 348: 
+        case 352: 
+        case 356: 
+        case 359: 
+        case 362: 
+          { 
+	/* JSP scriptlet begun (anywhere)
+	 * A consequence of the start anywhere possibility is that the
+	 *  incoming state must be checked to see if it's erroneous
+	 *  due to the order of precedence generated
+	 */
+	// begin sanity checks
+	if(yystate() == ST_JSP_CONTENT) {
+		// at the beginning?!
+		yypushback(1);
+		return JSP_CONTENT;
+	}
+	else if(yystate() == ST_BLOCK_TAG_SCAN) {
+		yypushback(2);
+		return doBlockTagScan();
+	}
+	else if(yystate() == ST_XML_COMMENT) {
+		yypushback(2);
+		return scanXMLCommentText();
+	}
+	else if(yystate() == ST_JSP_COMMENT) {
+		yypushback(2);
+		return scanJSPCommentText();
+	}
+	// finished sanity checks
+	fStateStack.push(yystate());
+	if(fStateStack.peek()==YYINITIAL) {
+		// the simple case, just a regular scriptlet out in content
+		if(Debug.debugTokenizer)
+			dump("\nJSP scriptlet start");//$NON-NLS-1$
+		yybegin(ST_JSP_CONTENT);
+		return JSP_SCRIPTLET_OPEN;
+	}
+	else {
+		if (Debug.debugTokenizer) {
+			System.out.println("begin embedded region: " + fEmbeddedHint);//$NON-NLS-1$
+		}
+		if(Debug.debugTokenizer)
+			dump("JSP scriptlet start");//$NON-NLS-1$
+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;
+		else if(yystate() == ST_CDATA_TEXT) {
+			fEmbeddedPostState = ST_CDATA_TEXT;
+			fEmbeddedHint = XML_CDATA_TEXT;
+		}
+		yybegin(ST_JSP_CONTENT);
+		assembleEmbeddedContainer(JSP_SCRIPTLET_OPEN, JSP_CLOSE);
+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {
+			yybegin(ST_BLOCK_TAG_SCAN);
+			return BLOCK_TEXT;
+		}
+		// required help for successive embedded regions
+		if(yystate() == ST_XML_TAG_NAME) {
+			fEmbeddedHint = XML_TAG_NAME;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;
+			fEmbeddedPostState = ST_XML_EQUALS;
+		}
+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {
+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;
+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;
+		}
+		return PROXY_CONTEXT;
+	}
+ }
+        case 762: break;
+        case 223: 
+          { 
+	fStateStack.push(yystate());
+	if(Debug.debugTokenizer)
+		dump("\ndeclaration start");//$NON-NLS-1$
+        yybegin(ST_XML_DECLARATION);
+	return XML_DECLARATION_OPEN;
+ }
+        case 763: break;
+        case 236: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("processing instruction end");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 764: break;
+        case 240: 
+          { 
+		// ended with nothing inside
+		fEmbeddedHint = UNDEFINED;
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 765: break;
+        case 241: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction end");//$NON-NLS-1$
+	fEmbeddedHint = UNDEFINED;
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 766: break;
+        case 258: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("JSP end");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return JSP_CLOSE;
+ }
+        case 767: break;
+        case 260: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("JSP end");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return JSP_DIRECTIVE_CLOSE;
+ }
+        case 768: break;
+        case 162: 
+        case 163: 
+          { 
+		return doBlockTagScan();
+	 }
+        case 769: break;
+        default: 
+          if (yy_input == YYEOF && yy_startRead == yy_currentPos) {
+            yy_atEOF = true;
+            yy_do_eof();
+              return null;
+          } 
+          else {
+            yy_ScanError(YY_NO_MATCH);
+          }
+      }
+    }
+  }    
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/JSPTokenizer.jflex b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/JSPTokenizer.jflex
new file mode 100644
index 0000000..0c21b1c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/JSPTokenizer.jflex
@@ -0,0 +1,2859 @@
+/*******************************************************************************

+ * Copyright (c) 2004, 2011 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

+ *     Frits Jalvingh - contributions for bug 150794

+ *******************************************************************************/

+

+package org.eclipse.jst.jsp.core.internal.parser.internal;

+

+import java.io.CharArrayReader;

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.Iterator;

+import java.util.List;

+

+import org.eclipse.jst.jsp.core.internal.Logger;

+import org.eclipse.jst.jsp.core.internal.contenttype.IntStack;

+import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;

+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;

+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockTokenizer;

+import org.eclipse.wst.sse.core.internal.ltk.parser.TagMarker;

+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;

+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;

+import org.eclipse.wst.sse.core.internal.util.Debug;

+import org.eclipse.wst.sse.core.utils.StringUtils;

+import org.eclipse.wst.xml.core.internal.parser.ContextRegionContainer;

+

+%%

+

+%{

+	private int fTokenCount = 0;

+ 

+	// required holders for white-space compacting

+	private boolean fShouldLoadBuffered = false;

+	private String fBufferedContext = null;

+	private int fBufferedStart = 1;

+	private int fBufferedLength = 0;

+	private ITextRegion fBufferedEmbeddedContainer = null;

+	private ITextRegion fProxyUnknownRegion = null;

+	private String f_context = null;

+

+	// state stack for handling embedded regions

+	private IntStack fStateStack = new IntStack();

+	// a "hint" as to what an embedded region should be evaluated

+	private String fEmbeddedHint = UNDEFINED;

+	// a "hint" as to what state to enter once an embedded region has

+	//   been completed

+	private int fEmbeddedPostState = YYINITIAL;

+	

+	// the container used to create embedded regions

+	private ContextRegionContainer fEmbeddedContainer = null;

+	private static final String PROXY_CONTEXT = "PROXY_CONTEXT";

+	private static final String PROXY_UNKNOWN_CONTEXT = "PROXY_UNKNOWN_CONTEXT";

+

+	private String context = null;

+	private int start = 0;

+	private int textLength = 0;

+	private int length = 0;

+

+	// offset for tracking position specific block tags

+	private int fOffset = 0;

+	

+	// the name of the current tag being opened

+	private String fCurrentTagName = null;

+

+	// the name of the current tag inside of an embedded region

+	private String internalTagName = null;

+	private String internalContext = null;

+

+	// the list of tag name BlockMarkers

+	private List fBlockMarkers = new ArrayList(0);

+	private List fNestablePrefixes = new ArrayList(1);

+	

+	// where the last internal container block was found

+	private int fLastInternalBlockStart = -1;

+

+	// required to not seek text blocks on an end tag

+	private boolean fIsBlockingEnabled = false;

+	private boolean fIsCaseSensitiveBlocking = true;

+

+	private static final boolean fForbidJSP = false;

+	

+	private int fELlevel = 0;

+

+	private JSPParserRegionFactory fRegionFactory = new JSPParserRegionFactory();

+

+	// Is the embedded tag a JSP tag

+	private boolean fEmbeddedTag = false;

+	// Is the non-embedded tag a JSP tag

+	private boolean fContainerTag = false;

+	// Is the tokenizer in a non-embedded tag (between < and >)

+	private boolean fInTagContainer = false;

+	// Is the tokenizer in an embedded tag (between < and >)

+	private boolean fInTagEmbedded = false;

+

+	/**

+	 * user method 

+	 */

+	public final void addBlockMarker(BlockMarker marker) {

+		if(containsTagName(marker.getTagName()))

+			return;

+		fBlockMarkers.add(marker);

+	}

+	/**

+	 * user method

+	 */

+	public final void addNestablePrefix(TagMarker marker) {

+		fNestablePrefixes.add(marker);

+	}

+	/* user method */

+	public List getNestablePrefixes() {

+		return fNestablePrefixes;

+	}

+	/**

+	 * user method

+	 */

+	private boolean isNestable(String tagName) {

+		//Iterator blocks = fNestablePrefixes.iterator();

+		//while(blocks.hasNext()) {

+		//	TagMarker marker = (TagMarker)blocks.next();

+		//	String markerName = marker.getTagName();

+		//	if(tagName.length() > markerName.length() + 1 && tagName.startsWith(markerName) && tagName.charAt(markerName.length()) == ':') {

+		//		return marker.isGlobal() || getOffset() >= marker.getMarker().getStart();

+		//	}

+		//}

+		//return false;

+		return true;

+	}

+	/**

+	 * user method 

+	 */

+	public final void removeNestablePrefix(String name) {

+		if (fNestablePrefixes != null) {

+			Iterator nestables = fNestablePrefixes.iterator();

+			while (nestables.hasNext()) {

+				if (((TagMarker) nestables.next()).getTagName().equalsIgnoreCase(name))

+					nestables.remove();

+			}

+		}

+	}

+	/**

+	 * user method 

+	 */

+	public final void removeBlockMarker(BlockMarker marker) {

+		fBlockMarkers.remove(marker);

+	}

+	/**

+	 * user method 

+	 */

+	public final void removeBlockMarker(String tagname) {

+		if (fBlockMarkers != null) {

+			Iterator blocks = fBlockMarkers.iterator();

+			while (blocks.hasNext()) {

+				if (((BlockMarker) blocks.next()).getTagName().equals(tagname))

+					blocks.remove();

+			}

+		}

+	}

+	/* user method */

+	private final void assembleEmbeddedTagSequence(String startType, String endTagName) {

+		assembleEmbeddedContainer(startType, null, endTagName);

+	}

+	/* user method */

+	private final void assembleEmbeddedContainer(String startType, String[] endTypes) {

+		assembleEmbeddedContainer(startType, endTypes, null);

+	}

+	/* user method */

+	private final void assembleEmbeddedContainer(String startType, String endType) {

+		assembleEmbeddedContainer(startType, new String[]{endType}, null);

+	}

+	/**

+	 *  user method 

+	 * 

+	 * Assembles an embedded container beginning with the given startType as

+	 * the first ContextRegion within it and of the type fEmbeddedHint.  The

+	 * endTypes[] array contains the context types that will cause a successful

+	 * exit.  Use of the endTagName parameter alters this behavior to force an

+	 * exit on an XML_TAG_CLOSE after seeing an XML_TAG_NAME whose significant

+	 * text matches the endTagName String.  All contents in between are

+	 * insignificant, and yes, this means comments are allowed inside.

+	 **/

+	private final void assembleEmbeddedContainer(String startType, String[] endTypes, String endTagName) {

+		// the context of the region being added to the embedded container

+		internalContext = startType;

+		// keep track of where this container began; to provide relative indeces for the regions

+		int containerStart = yychar;

+		boolean notFinished = true;

+		// keep track of where we seem to be so that the endTagName can be checked

+		boolean isInEndTag = false;

+		boolean isInFirstTag = true;

+		// create the embedded container and setup its "type"

+		if (fEmbeddedContainer == null) {

+			fEmbeddedContainer = new ContextRegionContainer();

+			fEmbeddedContainer.setType(fEmbeddedHint);

+			fEmbeddedContainer.setStart(containerStart);

+			// TODO: parent region needs to be set .... but not sure where to get it from 

+			//		fEmbeddedContainer.setParent(parentRegion);

+		}

+		int initialLength = fEmbeddedContainer.getRegions().size();

+		containerStart = fEmbeddedContainer.getStart();

+		while (notFinished) {

+			// add the region to the container

+			if (internalContext != null && internalContext != PROXY_CONTEXT) {

+				ITextRegion newToken = fRegionFactory.createToken(internalContext, yychar - containerStart, yylength(), yylength());

+				fEmbeddedContainer.getRegions().add(newToken);

+				fEmbeddedContainer.setLength(fEmbeddedContainer.getLength() + yylength());

+				fEmbeddedContainer.setTextLength(fEmbeddedContainer.getTextLength() + yylength());

+				// DW, 4/16/2003 token regions no longer have parents

+				//newToken.setParent(fEmbeddedContainer);

+			}

+			try {

+				// longscan determines whether to attempt a blockTagScan within the embedded container

+				boolean longscan = false;

+				// save the tokenizer state in case of a block tag scan

+				int previousState = yystate();

+				String previousCurrentTagName = fCurrentTagName;

+				int previousPostState = fEmbeddedPostState;

+				String previousEmbeddedHint = fEmbeddedHint;

+				// determine if a block tag scan is necessary

+				if (internalContext == XML_TAG_NAME) {

+					internalTagName = yytext();

+					if (endTagName != null && endTagName.length() == 0){

+						endTagName = internalTagName;

+					}

+					if(!isNestable(internalTagName)) {

+						internalTagName = null;

+						// snagged a tag name we shouldn't have

+						fEmbeddedPostState = ST_ABORT_EMBEDDED;

+						notFinished = false;

+					}

+				}

+				else if (internalContext == XML_TAG_OPEN || internalContext == XML_END_TAG_OPEN) {

+					internalTagName = null;

+				}

+				// do upkeep for endTagName usage; must be here since the next token could be the close

+				if (internalContext == XML_END_TAG_OPEN) {

+					isInEndTag = true;

+				} else if (internalContext == XML_TAG_CLOSE) {

+					isInFirstTag = isInEndTag = false;

+				} else {

+				 	ITextRegionList embeddedRegions = fEmbeddedContainer.getRegions();

+					if (embeddedRegions.size() > 2 && (embeddedRegions.get(embeddedRegions.size()-1)).getType() == XML_TAG_CLOSE && (embeddedRegions.get(embeddedRegions.size() - 3)).getType() == XML_TAG_OPEN && internalTagName != null) {

+						if (containsTagName(internalTagName)) {

+							longscan = true;

+							yybegin(ST_BLOCK_TAG_SCAN);

+						}

+					}

+				}

+				if (longscan)

+					fCurrentTagName = internalTagName;

+				// read the next region and context

+				internalContext = primGetNextToken();

+				if (longscan) {

+					// Returning from a block tag scan requires restoring some state variables

+					// as well as handling the block region and setting up for normal scanning

+					// inside the embedded container

+					ITextRegion newToken = fRegionFactory.createToken(internalContext, yychar - containerStart, yylength(), yylength());

+					fEmbeddedContainer.getRegions().add(newToken);

+					fEmbeddedContainer.setLength(fEmbeddedContainer.getLength() + yylength());

+					fEmbeddedContainer.setTextLength(fEmbeddedContainer.getTextLength() + yylength());

+					// DW, 4/16/2003 token regions no longer have parents

+					// newToken.setParent(fEmbeddedContainer);

+					longscan = false;

+					fEmbeddedPostState = previousPostState;

+					fEmbeddedHint = previousEmbeddedHint;

+					fCurrentTagName = previousCurrentTagName;

+					yybegin(previousState);

+					internalContext = primGetNextToken();

+				}

+			} catch (IOException e) {

+				// primGetNextToken() calls may throw an IOException

+				// catch and do nothing since the isEOF check below

+				// will properly exit if the input was too short

+			} catch (Exception f) {

+				// some other exception happened; never should

+				Logger.logException(f);

+			}

+			boolean isEndingType = yystate() == ST_ABORT_EMBEDDED;

+			ITextRegionList embeddedList = fEmbeddedContainer.getRegions();

+			if(!isEndingType) {

+				// check for ending context

+				if (endTagName == null) {

+					for (int i = 0; i < endTypes.length; i++) {

+						isEndingType = isEndingType || (internalContext == endTypes[i]) || (embeddedList.size() - initialLength) >= 2 && (embeddedList.get(embeddedList.size()-1)).getType() == endTypes[i];

+					}

+				}

+				else {

+					isEndingType = ((isInEndTag && internalContext == XML_TAG_CLOSE) || (isInFirstTag && internalContext == XML_EMPTY_TAG_CLOSE)) && internalTagName != null && internalTagName.equals(endTagName);

+				}

+			}

+			notFinished = notFinished && ((!isEndingType) && !isEOF() && (endTagName != null || internalContext != UNDEFINED) && !(internalContext == PROXY_CONTEXT && (embeddedList.get(embeddedList.size()-1)).getType() == UNDEFINED));

+		}

+		// finish adding the last context

+		if (internalContext != null && internalContext != PROXY_CONTEXT) {

+			ITextRegion newToken = fRegionFactory.createToken(internalContext, yychar - containerStart, yylength(), yylength());

+			fEmbeddedContainer.getRegions().add(newToken);

+			// DW, 4/16/2003 token regions no longer have parents

+			//newToken.setParent(fEmbeddedContainer);

+			fEmbeddedContainer.setLength(yychar - containerStart + yylength());

+			fEmbeddedContainer.setTextLength(yychar - containerStart + yylength());

+		}

+		yybegin(fEmbeddedPostState);

+	}

+	/* user method */

+	public final boolean isCaseSensitiveBlocking() {

+		return fIsCaseSensitiveBlocking;

+	}

+	/* user method */

+	public final void setCaseSensitiveBlocking(boolean newValue) {

+		fIsCaseSensitiveBlocking = newValue;

+	}

+	/* user method */

+	public boolean getBlockMarkerAllowsJSP() {

+		return getBlockMarkerAllowsJSP(fCurrentTagName);

+	}

+	/* user method */

+	public boolean getBlockMarkerAllowsJSP(String name) {

+		Iterator iterator = fBlockMarkers.iterator();

+		while(iterator.hasNext()) {

+			BlockMarker marker = (BlockMarker)iterator.next();

+			boolean casesensitive = marker.isCaseSensitive();

+			if(casesensitive && marker.getTagName().equals(name))

+				return marker.allowsJSP();

+			else if(!casesensitive && marker.getTagName().equalsIgnoreCase(name))

+				return marker.allowsJSP();

+		}

+		return true;

+	}

+	/* user method */

+	public boolean getBlockMarkerCaseSensitivity() {

+		return getBlockMarkerCaseSensitivity(fCurrentTagName);

+	}

+	public boolean getBlockMarkerCaseSensitivity(String name) {

+		Iterator iterator = fBlockMarkers.iterator();

+		while(iterator.hasNext()) {

+			BlockMarker marker = (BlockMarker)iterator.next();

+			boolean casesensitive = marker.isCaseSensitive();

+			if(casesensitive && marker.getTagName().equals(name))

+				return casesensitive;

+			else if(!casesensitive && marker.getTagName().equalsIgnoreCase(name))

+				return casesensitive;

+		}

+		return true;

+	}

+	/* user method */

+	public String getBlockMarkerContext() {

+		return getBlockMarkerContext(fCurrentTagName);

+	}

+	/* user method */

+	public String getBlockMarkerContext(String name) {

+		Iterator iterator = fBlockMarkers.iterator();

+		while(iterator.hasNext()) {

+			BlockMarker marker = (BlockMarker)iterator.next();

+			if(marker.getTagName().equals(name))

+				return marker.getContext();

+		}

+		return BLOCK_TEXT;

+	}

+	/* user method */

+	public List getBlockMarkers() {

+		return fBlockMarkers;

+	}

+	/* user method */

+	public final int getOffset() {

+		return fOffset + yychar;

+	}

+	private final boolean isBlockMarker() {

+		return isBlockMarker(fCurrentTagName);

+	}

+	private final boolean isBlockMarker(String tagName) {

+		if (!fIsBlockingEnabled)

+			return false;

+		return containsTagName(tagName);

+	}

+	/**

+	 * user method

+	 */

+	public final void beginBlockTagScan(String newTagName) {

+		beginBlockMarkerScan(newTagName, BLOCK_TEXT);

+	}

+	/**

+	 * user method

+	 *

+	 * Special tokenizer setup.  Allows tokenization to be initiated at the

+	 * start of a text block within a "newTagName" tag.

+	 *

+	 * Example: 

+	 *	Tokenizer toker = new Tokenizer();

+	 *	toker.setCaseSensitiveBlocking(false);

+	 *	toker.reset(new java.io.StringReader("afiuhqwkejhtasihgalkwhtq</scripter></scr></script>asgdasga"));

+	 *	toker.beginBlockMarkerScan("script", BLOCK_TEXT);

+	 *	toker.getRegions(); 

+	 *

+	 * Returns:

+	 *	BLOCK_TEXT: 0-40

+	 *	XML_END_TAG_OPEN: 41-42

+	 *	XML_TAG_NAME: 43-48

+	 *	XML_TAG_CLOSE: 49-49

+	 *	XML_CONTENT: 50-57

+	 *

+	 */

+	public final void beginBlockMarkerScan(String newTagName, String blockcontext) {

+		yybegin(ST_BLOCK_TAG_SCAN);

+		fCurrentTagName = newTagName;

+	}

+

+/**

+ * Method doScan.

+ * 

+ * Returns a context region for all of the text from the current position upto the end of input or

+ * to right *before* the first occurence of searchString

+ * 

+ * @param searchString - target string to search for ex.: "-->", "</tagname"

+ * @param requireTailSeparator - whether the target must be immediately followed by whitespace or '>'

+ * @param allowJSP - check for and allow for JSP markup <%%>

+ * @param context - the context of the scanned region if non-zero length

+ * @param exitState - the state to go to if the region was of non-zero length

+ * @param abortState - the state to go to if the searchString was found immediately

+ * @return String - the context found: the desired context on a non-zero length match, the abortContext on immediate success

+ * @throws IOException

+ */

+private final String doScan(String searchString, boolean requireTailSeparator, boolean allowJSP, boolean allowCDATA, String searchContext, int exitState, int immediateFallbackState) throws IOException {

+	boolean stillSearching = true;

+	boolean wasBlockingEnabled = fIsBlockingEnabled;

+	try {

+		// Disable further block (probably)

+		fIsBlockingEnabled = false;

+		int searchStringLength = searchString.length();

+		int n = 0;

+		char lastCheckChar;

+		int i;

+		boolean same = false;

+		// Check for JSP starts ("<%") if the tag is global like SCRIPT or STYLE

+		boolean checkJSPs = allowJSP && !fForbidJSP;

+		boolean checkedForJSPsOnce = !checkJSPs;

+		boolean checkedJSPsAtStartOnce = false;

+		

+		while (stillSearching) {

+			n = 0;

+			// Ensure that enough data from the input exists to compare against the search String.

+			n = yy_advance();

+			while(n != YYEOF && yy_currentPos < searchStringLength)

+				n = yy_advance();

+	//		c = (char) n;

+			// If the input was too short or we've exhausted the input, stop immediately.

+			if (n == YYEOF && checkedForJSPsOnce) {

+				stillSearching = false;

+			}

+			else {

+				/**

+				 * Look for starting JSPs "<%"

+				 */

+				checkedForJSPsOnce = true;

+				// 1) yy_currentPos - searchStringLength : There's at least searchStringLength of input available; once that's read, check for JSPs

+				// ---

+				// Look for a JSP beginning at current-searchStringLength; if so, backup and switch scanner states to handle it.

+				// Ensure that we've not encountered a complete block (<%%>) that was *shorter* than the closeTagString and

+				// thus found twice at current-targetLength [since the first scan would have come out this far anyway].

+				if(checkJSPs && yy_currentPos > searchStringLength && yy_currentPos - searchStringLength != fLastInternalBlockStart && 

+					yy_buffer[yy_currentPos - searchStringLength] == '<' && yy_buffer[yy_currentPos - searchStringLength + 1] == '%') {

+					fLastInternalBlockStart = yy_markedPos = yy_currentPos - searchStringLength;

+					yy_currentPos = yy_markedPos + 1;

+					int resumeState = yystate();

+					yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);

+					if(yy_markedPos == yy_startRead) {

+						String jspContext = primGetNextToken();

+						yybegin(resumeState);

+						return jspContext;

+					}

+					return searchContext;

+				}

+				// 2) yy_currentPos - jspstarter.length : There's not searchStringLength of input available; check for a JSP 2 spots back in what we could read

+				// ---

+				// Look for a JSP beginning at the current position; this case wouldn't be handled by the preceding section

+				// since it relies upon *having* closeTagStringLength amount of input to work as designed.  Must be sure we don't

+				// spill over the end of the buffer while checking.

+				else if(checkJSPs && yy_startRead != fLastInternalBlockStart && yy_currentPos > 0 && yy_currentPos < yy_buffer.length - 1 &&

+						yy_buffer[yy_currentPos - 1] == '<' && yy_buffer[yy_currentPos] == '%') {

+					fLastInternalBlockStart = yy_markedPos = yy_currentPos - 1;

+					yy_currentPos = yy_markedPos + 1;

+					int resumeState = yystate();

+					yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);

+					if(yy_markedPos == yy_startRead) {

+						String jspContext = primGetNextToken();

+						yybegin(resumeState);

+						return jspContext;

+					}

+					return searchContext;

+				}

+				// 3) yy_currentPos..(yy_currentPos+jspStartlength-1) : Check at the start of the block one time

+				// ---

+				// Look for a JSP beginning immediately in the block area; this case wouldn't be handled by the preceding section

+				// since it relies upon yy_currentPos equaling exactly the previous end +1 to work as designed.

+				else if(checkJSPs && !checkedJSPsAtStartOnce && yy_startRead != fLastInternalBlockStart && yy_startRead > 0 &&

+						yy_startRead < yy_buffer.length - 1 && yy_buffer[yy_startRead] == '<' && yy_buffer[yy_startRead + 1] == '%') {

+					checkedJSPsAtStartOnce = true;

+					fLastInternalBlockStart = yy_markedPos = yy_startRead;

+					yy_currentPos = yy_markedPos + 1;

+					int resumeState = yystate();

+					yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);

+					if(yy_markedPos == yy_startRead) {

+						String jspContext = primGetNextToken();

+						yybegin(resumeState);

+						return jspContext;

+					}

+					return searchContext;

+				}

+	

+	

+				/**

+				 * Look for starting CDATA "<![CDATA["

+				 */

+				// 1) yy_currentPos - searchStringLength: There's at least searchStringLength of input available; once that's read, check for CDATA

+				// ---

+				// Look for a CDATA beginning at current-searchStringLength; if so, backup and switch scanner states to handle it.

+				// Ensure that we've not encountered a complete block (<[!CDATA[]]>) that was *shorter* than the closeTagString and

+				// thus found twice at current-targetLength [since the first scan would have come out this far anyway].

+	/*			if(checkCDATA && yy_currentPos > searchStringLength && yy_currentPos + searchStringLength < yy_buffer.length && yy_currentPos - searchStringLength != fLastInternalBlockStart && 

+					charsMatch(cdataStarter, yy_buffer, 0, yy_currentPos - searchStringLength)) {

+					fLastInternalBlockStart = yy_markedPos = yy_currentPos - searchStringLength;

+					yy_currentPos = yy_markedPos + 1;

+					int resumeState = yystate();

+					// go to a state where CDATA can be found

+					if (fEmbeddedContainer == null) {

+						fEmbeddedContainer = new ContextRegionContainer();

+						fEmbeddedContainer.setType(searchContext);

+						fEmbeddedContainer.setStart(yychar);

+					}

+					ITextRegion newToken = fRegionFactory.createToken(searchContext, yychar, yylength(), yylength());

+					fEmbeddedContainer.getRegions().add(newToken);

+					fEmbeddedContainer.setLength(fEmbeddedContainer.getLength() + yylength());

+					fEmbeddedContainer.setTextLength(fEmbeddedContainer.getTextLength() + yylength());

+					yybegin(YYINITIAL);

+					String context = primGetNextToken();

+					if(context.equals(XMLRegionContexts.XML_CDATA_OPEN)) {

+						assembleEmbeddedContainer(XMLRegionContexts.XML_CDATA_OPEN, XMLRegionContexts.XML_CDATA_CLOSE);

+					}

+					yybegin(resumeState);

+					return searchContext;

+				}

+	*//*

+				// 2) yy_currentPos - cdataStarter.length: There's not searchStringLength of input available; check for a CDATA right here spots back in what we could read

+				// ---

+				// Look for a JSP beginning at the current position; this case wouldn't be handled by the preceding section

+				// since it relies upon *having* closeTagStringLength amount of input to work as designed.  Must be sure we don't

+				// spill over the end of the buffer while checking.

+				else if(checkCDATA && yy_startRead != fLastInternalBlockStart && yy_currentPos > 0 && yy_currentPos < yy_buffer.length - 1 &&

+						yy_buffer[yy_currentPos - 1] == '<' && yy_buffer[yy_currentPos] == '%') {

+					fLastInternalBlockStart = yy_markedPos = yy_currentPos - 1;

+					yy_currentPos = yy_markedPos + 1;

+					int resumeState = yystate();

+					yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);

+					if(yy_markedPos == yy_startRead) {

+						String jspContext = primGetNextToken();

+						yybegin(resumeState);

+						return jspContext;

+					}

+					return searchContext;

+				}

+				// 3) yy_currentPos : Check at the start of the block one time

+				// ---

+				// Look for a JSP beginning immediately in the block area; this case wouldn't be handled by the preceding section

+				// since it relies upon yy_currentPos equaling exactly the previous end +1 to work as designed.

+				else if(checkCDATA && !checkedForCDATAOnce && yy_startRead != fLastInternalBlockStart && yy_startRead > 0 &&

+						yy_startRead < yy_buffer.length - 1 && yy_buffer[yy_startRead] == '<' && yy_buffer[yy_startRead + 1] == '%') {

+					checkedForCDATAOnce = true;

+					fLastInternalBlockStart = yy_markedPos = yy_startRead;

+					yy_currentPos = yy_markedPos + 1;

+					int resumeState = yystate();

+					yybegin(ST_BLOCK_TAG_INTERNAL_SCAN);

+					if(yy_markedPos == yy_startRead) {

+						String jspContext = primGetNextToken();

+						yybegin(resumeState);

+						return jspContext;

+					}

+					return searchContext;

+				}

+	*/

+				// Check the characters in the target versus the last targetLength characters read from the buffer

+				// and see if it matches

+				if (n == YYEOF) {

+					stillSearching = false;

+				}

+				else {

+					same = true;

+					// safety check for array accesses

+					if(yy_currentPos >= searchStringLength && yy_currentPos <= yy_buffer.length) {

+						for(i = 0; i < searchStringLength && same; i++) {

+							if(fIsCaseSensitiveBlocking)

+								same = yy_buffer[i + yy_currentPos - searchStringLength] == searchString.charAt(i);

+							else

+								same = Character.toLowerCase(yy_buffer[i + yy_currentPos - searchStringLength]) == Character.toLowerCase(searchString.charAt(i));

+						}

+					}

+					// safety check failed; no match is possible right now

+					else {

+						same = false;

+					}

+				}

+				if (same && requireTailSeparator && yy_currentPos < yy_buffer.length) {

+					// Additional check for close tags to ensure that targetString="</script" doesn't match

+					// "</scriptS"

+					lastCheckChar = yy_buffer[yy_currentPos];

+					// Succeed on "</script>" and "</script "

+					if(lastCheckChar == '>' || Character.isWhitespace(lastCheckChar))

+						stillSearching = false;

+				}

+				else {

+					stillSearching = !same || (yy_currentPos < yy_startRead + searchStringLength);

+				}

+			}

+		}

+		if (n != YYEOF || same) {

+			// We've stopped short of the end or definitely found a match

+			yy_markedPos = yy_currentPos - searchStringLength;

+			yy_currentPos = yy_markedPos + 1;

+			// If the searchString occurs at the very beginning of what would have

+			// been a Block, resume scanning normally immediately

+			if (yy_markedPos == yy_startRead) {

+				yybegin(immediateFallbackState);

+				return primGetNextToken();

+			}

+		}

+		else {

+			// We ran through the rest of the input

+			yy_markedPos = yy_currentPos;

+			yy_currentPos++;

+		}

+		yybegin(exitState);

+		// If the ending occurs at the very beginning of what would have

+		// been a Block, resume scanning normally immediately

+		if(yy_markedPos == yy_startRead)

+			return primGetNextToken();

+		return searchContext;

+	}

+	finally {

+		fIsBlockingEnabled = wasBlockingEnabled;

+	}

+}

+/**

+ * user method 

+ * does a lookahead for the current tag name

+ */

+private final String doBlockTagScan() throws IOException {

+	fIsCaseSensitiveBlocking = getBlockMarkerCaseSensitivity();

+	return doScan("</" + fCurrentTagName, true, getBlockMarkerAllowsJSP(), true, getBlockMarkerContext(fCurrentTagName), YYINITIAL, YYINITIAL);

+}

+	/**

+	 * user method

+	 *

+	 * Converts the raw context String returned by the primGetNextToken()

+	 * method into a full ITextRegion by pulling in values for the

+	 * current offset within the scanning text.

+	 *

+	 * Returns null when EOF is encountered and attaches intermittently

+	 * discovered whitespace onto the end of useful regions.

+	 *

+	 * Note that this algorithm caches the token following the one being returned

+	 * so that whitespace can be collapsed.

+	 */

+	public final ITextRegion getNextToken() throws IOException {

+		fEmbeddedContainer = null;

+		// load the starting non-whitespace token (assume that it is so)

+		if (fShouldLoadBuffered) {

+			if (fBufferedEmbeddedContainer != null) {

+				ITextRegion container = fBufferedEmbeddedContainer;

+				fBufferedEmbeddedContainer = null;

+				fShouldLoadBuffered = false;

+				return container;

+			}

+			context = fBufferedContext;

+			start = fBufferedStart;

+			textLength = length = fBufferedLength;

+			fShouldLoadBuffered = false;

+		} else {

+			context = primGetNextToken();

+			if (context == PROXY_CONTEXT) {

+				return fEmbeddedContainer;

+			} else if (context == XML_TAG_NAME || f_context == JSP_ROOT_TAG_NAME || f_context == JSP_DIRECTIVE_NAME) {

+				if(containsTagName(yy_buffer, yy_startRead, yy_markedPos-yy_startRead))

+					fCurrentTagName = yytext();

+				else

+					fCurrentTagName = null;

+			} else if (context == XML_TAG_OPEN) {

+				fIsBlockingEnabled = true;

+			} else if (context == XML_END_TAG_OPEN) {

+				fIsBlockingEnabled = false;

+			}

+			start = yychar;

+			textLength = length = yylength();

+			if (yy_atEOF) {

+				fTokenCount++;

+				return null;

+			}

+		}

+		// store the next token

+		f_context = primGetNextToken();

+		if (f_context == PROXY_CONTEXT) {

+			fBufferedEmbeddedContainer = fEmbeddedContainer;

+			fShouldLoadBuffered = true;

+		} else if (f_context == XML_TAG_NAME || f_context == JSP_ROOT_TAG_NAME || f_context == JSP_DIRECTIVE_NAME) {

+			if(containsTagName(yy_buffer, yy_startRead, yy_markedPos-yy_startRead))

+				fCurrentTagName = yytext();

+			else

+				fCurrentTagName = null;

+		} else if (f_context == XML_TAG_OPEN) {

+			fIsBlockingEnabled = true;

+		} else if (f_context == XML_END_TAG_OPEN) {

+			fIsBlockingEnabled = false;

+		} else if (f_context == PROXY_UNKNOWN_CONTEXT) {

+			fBufferedEmbeddedContainer = fProxyUnknownRegion;

+		}

+		fBufferedContext = f_context;

+		fBufferedStart = yychar;

+		fBufferedLength = yylength();

+		fShouldLoadBuffered = true;

+		if (fBufferedContext == WHITE_SPACE) {

+			fShouldLoadBuffered = false;

+			length += fBufferedLength;

+		}

+		if (context == null) {

+			// EOF

+			if (Debug.debugTokenizer) {

+				System.out.println(getClass().getName() + " discovered " + fTokenCount + " tokens."); //$NON-NLS-2$//$NON-NLS-1$

+			}

+			return null;

+		}

+		fTokenCount++;

+		return fRegionFactory.createToken(context, start, textLength, length, null, fCurrentTagName);

+	}

+	/* user method */

+	public JSPTokenizer(){

+		super();

+	}

+	/* user method */

+	public JSPTokenizer(char[] charArray){

+			this(new CharArrayReader(charArray));

+	}

+	/* user method */

+	public void reset(char[] charArray) {

+		reset(new CharArrayReader(charArray), 0);

+	}

+	/* user method */

+	public void reset(char[] charArray, int newOffset) {

+		reset(new CharArrayReader(charArray), newOffset);

+	}

+	/* user method */

+	public void reset(java.io.InputStream in) {

+		reset(new java.io.InputStreamReader(in), 0);

+	}

+	/* user method */

+	public void reset(java.io.InputStream in, int newOffset) {

+		reset(new java.io.InputStreamReader(in), newOffset);

+	}

+	/* user method */

+	public void reset(java.io.Reader in) {

+		reset(in, 0);

+	}

+	/**

+	 * user method *

+	 *

+	 * Reset internal counters and vars to "newly created" values, in the hopes

+	 * that resetting a pre-existing tokenizer is faster than creating a new one.

+	 *

+	 * This method contains code blocks that were essentially duplicated from the

+	 * <em>generated</em> output of this specification before this method was

+	 * added.  Those code blocks were under the above copyright.

+	 */

+	public void reset(java.io.Reader in, int newOffset) {

+		if (Debug.debugTokenizer) {

+			System.out.println("resetting tokenizer");//$NON-NLS-1$

+		}

+		fOffset = newOffset;

+	

+		/* the input device */

+		yy_reader = in;

+	

+		/* the current state of the DFA */

+		yy_state = 0;

+	

+		/* the current lexical state */

+		yy_lexical_state = YYINITIAL;

+	

+		/* this buffer contains the current text to be matched and is

+		the source of the yytext() string */

+		java.util.Arrays.fill(yy_buffer, (char)0);

+	

+		/* the textposition at the last accepting state */

+		yy_markedPos = 0;

+	

+		/* the textposition at the last state to be included in yytext */

+		yy_pushbackPos = 0;

+	

+		/* the current text position in the buffer */

+		yy_currentPos = 0;

+	

+		/* startRead marks the beginning of the yytext() string in the buffer */

+		yy_startRead = 0;

+	

+		/** 

+		 * endRead marks the last character in the buffer, that has been read

+		 * from input 

+		 */

+		yy_endRead = 0;

+	

+		/* number of newlines encountered up to the start of the matched text */

+		//yyline = 0;

+	

+		/* the number of characters up to the start of the matched text */

+		yychar = 0;

+	

+		/* yy_atEOF == true <=> the scanner has returned a value for EOF */

+		yy_atEOF = false;

+	

+		/* denotes if the user-EOF-code has already been executed */

+		yy_eof_done = false;

+	

+	

+		/* user vars: */

+		fTokenCount = 0;

+	 

+		fShouldLoadBuffered = false;

+		fBufferedContext = null;

+		fBufferedStart = 1;

+		fBufferedLength = 0;

+		fStateStack = new IntStack();

+	

+		fLastInternalBlockStart = -1;

+	

+		context = null;

+		start = 0;

+		textLength = 0;

+		length = 0;

+	

+		fEmbeddedContainer = null;

+		

+		fELlevel = 0;

+	}

+	/**

+	 * user method

+	 *

+	 */

+	public BlockTokenizer newInstance() {

+		JSPTokenizer newInstance = new JSPTokenizer();

+		// global tagmarkers can be shared; they have no state and 

+		// are never destroyed (e.g. 'release')

+		for(int i = 0; i < fBlockMarkers.size(); i++) {

+			BlockMarker blockMarker = (BlockMarker) fBlockMarkers.get(i);

+			if(blockMarker.isGlobal())

+				newInstance.addBlockMarker(blockMarker);

+		}

+		for(int i = 0; i < fNestablePrefixes.size(); i++) {

+			TagMarker marker = (TagMarker) fNestablePrefixes.get(i);

+			if(marker.isGlobal())

+				newInstance.addNestablePrefix(marker);

+		}

+		return newInstance;

+	}

+	/* user method */

+	private final String scanXMLCommentText() throws IOException {

+		// Scan for '-->' and return the text up to that point as

+		//   XML_COMMENT_TEXT unless the string occurs IMMEDIATELY, in which

+		//  case change to the ST_XML_COMMENT_END state and return the next

+		//  context as usual.

+		return doScan("-->", false, true, true, XML_COMMENT_TEXT, ST_XML_COMMENT_END, ST_XML_COMMENT_END);

+	}

+	/* user method */

+	private final String scanJSPCommentText() throws IOException {

+		// Scan for '--%>' and return the text up to that point as

+		//   JSP_COMMENT_TEXT unless the string occurs IMMEDIATELY, in which

+		//  case change to the ST_JSP_COMMENT_END state and return the next

+		//  context as usual.

+		return doScan("--%>", false, false, true, JSP_COMMENT_TEXT, ST_JSP_COMMENT_END, ST_JSP_COMMENT_END);

+	}

+	

+	/* user method */

+	private boolean isJspTag() {

+		return (fContainerTag && fEmbeddedContainer != null) || (fContainerTag && fInTagContainer) || (fEmbeddedTag && fInTagEmbedded);

+	}

+%}

+

+%eof{

+// do nothing, this is the downstream parser's job

+%eof}

+

+%public

+%class JSPTokenizer

+%implements BlockTokenizer, DOMJSPRegionContexts

+%function primGetNextToken

+%type String

+%char

+%unicode

+%pack

+

+%state ST_CDATA_TEXT

+%state ST_CDATA_END

+%state ST_XML_COMMENT

+%state ST_XML_COMMENT_END

+%state ST_PI

+%state ST_PI_WS

+%state ST_PI_CONTENT

+%state ST_XML_PI_ATTRIBUTE_NAME

+%state ST_XML_PI_EQUALS

+%state ST_XML_PI_ATTRIBUTE_VALUE

+%state ST_XML_PI_TAG_CLOSE

+%state ST_DHTML_ATTRIBUTE_NAME

+%state ST_DHTML_EQUALS

+%state ST_DHTML_ATTRIBUTE_VALUE

+%state ST_DHTML_TAG_CLOSE

+

+// scriptlet state(s)

+%state ST_JSP_CONTENT

+%state ST_JSP_DIRECTIVE_NAME

+%state ST_JSP_DIRECTIVE_NAME_WHITESPACE

+%state ST_JSP_DIRECTIVE_ATTRIBUTE_NAME

+%state ST_JSP_DIRECTIVE_EQUALS

+%state ST_JSP_DIRECTIVE_ATTRIBUTE_VALUE

+

+// normal tag states

+%state ST_XML_TAG_NAME

+%state ST_XML_ATTRIBUTE_NAME

+%state ST_XML_EQUALS

+%state ST_XML_ATTRIBUTE_VALUE

+

+// declaration (DTD) states

+%state ST_XML_DECLARATION

+%state ST_XML_DECLARATION_CLOSE

+

+%state ST_XML_DOCTYPE_DECLARATION

+%state ST_XML_DOCTYPE_EXTERNAL_ID

+%state ST_XML_DOCTYPE_ID_PUBLIC

+%state ST_XML_DOCTYPE_ID_SYSTEM

+

+%state ST_XML_ELEMENT_DECLARATION

+%state ST_XML_ELEMENT_DECLARATION_CONTENT

+

+%state ST_XML_ATTLIST_DECLARATION

+%state ST_XML_ATTLIST_DECLARATION_CONTENT

+

+

+%state ST_BLOCK_TAG_SCAN

+%state ST_BLOCK_TAG_INTERNAL_SCAN

+

+%state ST_JSP_COMMENT

+%state ST_JSP_COMMENT_END

+

+%state ST_JSP_ATTRIBUTE_VALUE

+%state ST_XML_ATTRIBUTE_VALUE_SQUOTED

+%state ST_XML_ATTRIBUTE_VALUE_DQUOTED

+

+%state ST_ABORT_EMBEDDED

+

+%state ST_JSP_EL

+%state ST_JSP_EL_SQUOTES

+%state ST_JSP_EL_DQUOTES

+%state ST_JSP_EL_SQUOTES_END

+%state ST_JSP_EL_DQUOTES_END

+

+%state ST_JSP_DQUOTED_EL

+%state ST_JSP_SQUOTED_EL

+

+%state ST_JSP_VBL

+%state ST_JSP_VBL_SQUOTES

+%state ST_JSP_VBL_DQUOTES

+%state ST_JSP_VBL_SQUOTES_END

+%state ST_JSP_VBL_DQUOTES_END

+

+%state ST_JSP_DQUOTED_VBL

+%state ST_JSP_SQUOTED_VBL

+

+// Letter = ([A-Za-z])

+// Digit = ([0-9])

+

+/**

+ * smaller tokens

+ */

+genericTagOpen       = <

+genericTagClose      = >

+genericEndTagOpen    = <\/

+genericEmptyTagClose = \/>

+

+PIstart = <\?

+PIend   = \?>

+

+

+// [1] document ::= prolog element Misc*

+document = ({prolog} {element} {Misc}*)

+

+// [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]

+ //Char = (.)

+Char = [\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD] 

+

+// [3] S ::= (0x20 | 0x9 | 0xD | 0xA)+

+S = [\x20\x09\x0D\x0A]+

+

+// [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender

+NameChar = ({Letter} | {Digit} | \. | \- | _ | : | {CombiningChar} | {Extender})

+

+// [5] Name ::= (Letter | '_' | ':') NameChar*

+//Name = ({NameChar}{NameChar}*)

+Name = ({Letter} | _ | :){NameChar}*

+

+// [6] Names ::= {Name} ({S} {Name})*

+Names = ({Name} ({S} {Name})*)

+

+// [7] Nmtoken ::= (NameChar)+

+Nmtoken = ({NameChar}+)

+

+// [8] Nmtokens ::= Nmtoken (S Nmtoken)*

+Nmtokens = ({Nmtoken} ({S} {Nmtoken})*)

+

+// [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |  "'" ([^%&'] | PEReference | Reference)* "'"

+EntityValue = (\" ([^%&\"] | {PEReference} | {Reference})* \" |  \' ([^%&\'] | {PEReference} | {Reference})* \')

+

+// \x24 = '$', \x7b = '{', \x23 = '#'

+// [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |  "'" ([^<&'] | Reference)* "'"

+AttValue = ( \"([^<"\x24\x23] | [\x24\x23][^\x7b\x3c"] | \\[\x24\x23][\x7b] | {Reference})* [\x24\x23]*\" | \'([^<'\x24\x23] | [\x24\x23][^\x7b\x3c'] | \\[\x24\x23][\x7b] | {Reference})*[\x24\x23]*\'  | ([^\'\"\040\011\012\015<>/]|\/+[^\'\"\040\011\012\015<>/] )*)

+

+// As Attvalue, but accepts escaped versions of the lead-in quote also

+QuotedAttValue = ( \"([^<"\x24\x23] | [\x24\x23][^\x7b"] | \\[\x24\x23][\x7b] | \\\" | {Reference})*[\x24\x23]*\" | \'([^<'\x24\x23] | [\x24\x23][^\x7b'] | \\[\x24\x23][\x7b] | \\\' | {Reference})*[\x24\x23]*\'  | ([^\'\"\040\011\012\015<>/]|\/+[^\'\"\040\011\012\015<>/] )*)

+

+// [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") 

+SystemLiteral = ((\" [^\"]* \") | (\' [^\']* \')) 

+

+// [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"

+PubidLiteral = (\" {PubidChar}* \" | \' ({PubidChar}\')* "'")

+

+// [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]

+PubidChar = ([\040\015\012] | [a-zA-Z0-9] | [\-\'()\+,.\/:=?;!\*#@\$_%])

+

+// [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)

+// implement lookahead behavior during action definition

+CharData = ([^<&(\]\]>)]*)

+

+// [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'

+CommentStart = (<!\-\-)

+CommentEnd   = (\-\->)

+Comment = ({CommentStart}.*{CommentEnd})

+

+// [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'

+PI = (<\?{PITarget} {Char}* \?>)

+

+// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))

+PITarget = ({Name}((X|x)(M|m)(L|l)))

+

+// [18] CDSect ::= CDStart CData CDEnd

+CDSect = ({CDStart}{CData}{CDEnd})

+

+// [19] CDStart ::= '<![CDATA['

+CDStart = <!\[CDATA\[

+

+// [20] CData ::= (Char* - (Char* ']]>' Char*)) 

+// implement lookahead behavior during action definition

+CData = ([^(\]\]>)]*)

+

+// [21] CDEnd ::= ']]>'

+CDEnd = (\]\]>)

+

+// [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?

+prolog = ({XMLDecl}? {Misc}* ({doctypedecl} {Misc}*)?)

+

+// [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'

+XMLDecl = (<\?xml {VersionInfo} {EncodingDecl}? {SDDecl}? {S}? \?>)

+

+// [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")

+VersionInfo = ({S}version{Eq}(\'{VersionNum}\' | \"{VersionNum}\"))

+

+// [25] Eq ::= S? '=' S?

+Eq = (\=)

+

+// [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+

+VersionNum = (([a-zA-Z0-9_.:]|\-)+)

+

+// [27] Misc ::= Comment | PI |  S

+Misc = ({Comment} | {PI} | {S})

+

+// [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)?  S? ('[' (markupdecl | PEReference | S)* ']' S?)? '>'

+doctypedecl = (<\!DOCTYPE{S}{Name} ({S}{ExternalID})? {S}? (\[ ({markupdecl}|{PEReference}|{S})* \]{S}?)?>)

+

+// [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment

+markupdecl = ({elementdecl} | {AttlistDecl} | {EntityDecl} | {NotationDecl} | {PI} | {Comment})

+

+// [30] extSubset ::= TextDecl? extSubsetDecl

+extSubset = ({TextDecl}? {extSubsetDecl})

+

+// [31] extSubsetDecl ::= ( markupdecl | conditionalSect | PEReference | S )*

+extSubsetDecl = (( {markupdecl} | {conditionalSect} | {PEReference} | {S} )*)

+

+// [32]  SDDecl  ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"'))

+SDDecl  = ({S}standalone{Eq}{S}*((\'(yes|no)\')|(\"(yes|no)\")))

+

+// [33]  LanguageID  ::= Langcode ('-' Subcode)*

+LanguageID  = ({Langcode}(\-{Subcode})*)

+

+// [34]  Langcode ::= ISO639Code |  IanaCode |  UserCode

+Langcode = ({ISO639Code} |  {IanaCode} |  {UserCode})

+

+// [35]  ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])

+ISO639Code = (([a-z]|[A-Z])([a-z]|[A-Z]))

+

+// [36]  IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+

+IanaCode = ((i|I)\-([a-z]|[A-Z])+)

+

+// [37]  UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+

+UserCode = ((x|X)\-([a-z]|[A-Z])+)

+

+// [38]  Subcode ::= ([a-z] | [A-Z])+

+Subcode = (([a-z]|[A-Z])+)

+

+// [39]  element  ::= EmptyElemTag | STag content ETag

+element  = ({EmptyElemTag} | {STag} {content} {ETag})

+

+// [40]  STag  ::= '<' Name (S Attribute)* S? '>'

+STag = (<{Name}({S}{Attribute})*{S}?>)

+

+// [41]  Attribute ::= Name Eq AttValue

+Attribute = ({Name}{S}*{Eq}{S}*{AttValue})

+

+// [42]  ETag  ::= 'Name S? '>'

+ETag = (<\/{Name}{S}?>)

+

+// [43]  content  ::= (element | CharData | Reference | CDSect | PI | Comment)*

+content = (({element} | {CharData} | {Reference} | {CDSect} | {PI} | {Comment})*)

+

+// [44]  EmptyElemTag  ::= '<' Name (S Attribute)* S? '/>'

+EmptyElemTag = (<{Name}({S}{Attribute})*{S}?\/>)

+

+// [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'

+elementdecl = (<\!ELEMENT{S}{Name}{S}{contentspec}{S}?>)

+

+// [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children

+contentspec = (EMPTY|ANY|{Mixed}|{children})

+

+// [47] children ::= (choice | seq) ('?' | '*' | '+')?

+children = (({choice}|{seq})(\?|\*|\+)?)

+

+// CAUSES LOOP THROUGH DEFS OF CHOICE AND SEQ

+// [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?

+cp = (({Name} | {choice} | {seq}) (\?|\*|\+)?)

+

+// [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'

+// choice = \({S}?{cp}({S}?\|{S}?{cp})*{S}?\)

+choice = \({S}?{Name}({S}?\|{S}?{Name})*{S}?\)

+

+// [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'

+// seq = (\({S}?{cp}({S}?\,{S}?{cp})*{S}?\))

+seq = (\({S}?{Name}({S}?\,{S}?{Name})*{S}?\))

+

+// [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S?  ')*' | '(' S? '#PCDATA' S? ')'

+Mixed = ({S}?\#PCDATA({S}?\|{S}?{Name})*{S}?)*\|({S}?\#PCDATA{S}?)

+

+// [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'

+AttlistDecl = (<\!ATTLIST{S}{Name}{AttDef}*{S}?>)

+

+// [53] AttDef ::= S Name S AttType S DefaultDecl

+AttDef = ({S}{Name}{S}{AttType}{S}{DefaultDecl})

+

+// [54] AttType ::= StringType | TokenizedType | EnumeratedType 

+AttType = ({StringType} | {TokenizedType} | {EnumeratedType})

+

+// [55] StringType ::= 'CDATA'

+StringType = (CDATA)

+

+// [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'

+TokenizedType = (ID|IDREF|IDREFS|ENTITY|ENTITIES|NMTOKEN|NMTOKENS)

+

+// [57] EnumeratedType ::= NotationType | Enumeration 

+EnumeratedType = ({NotationType} | {Enumeration})

+

+// [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')' 

+NotationType = (NOTATION{S}\({S}?{Name}({S}?\|{S}?{Name})*{S}?\))

+

+// [59] Enumeration ::= '(' S? Nmtoken (S? '|' S?  Nmtoken)* S? ')'

+Enumeration = (\({S}?{Nmtoken}({S}?\|{S}?{Nmtoken})*{S}?\))

+

+// [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)

+DefaultDecl = (\#REQUIRED|\#IMPLIED|((\#FIXED{S})?{AttValue}))

+

+// [61] conditionalSect ::= includeSect | ignoreSect 

+conditionalSect = ({includeSect} | {ignoreSect})

+

+// [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>' 

+includeSect = (<\!\[{S}?INCLUDE{S}?\[{extSubsetDecl}\]\]>)

+

+// [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'

+ignoreSect = (<\!\[{S}?IGNORE{S}?\[{ignoreSectContents}*\]\]>)

+

+// [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*

+ignoreSectContents = ({Ignore}(<\!\[{ignoreSectContents}\]\]>{Ignore})*)

+

+// [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)

+Ignore =  ([^(\<\!\[|\]\]\>)]*)

+

+// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'

+CharRef = (&#[0-9]+;|&#x[0-9a-fA-F]+;)

+

+// [67] Reference ::= EntityRef | CharRef

+Reference = ({EntityRef} | {CharRef})

+

+// [68] EntityRef = '&' Name ';'

+EntityRef = (&{Name};)

+

+// [69] PEReference ::= '%' Name ';'

+PEReference = (%{Name};)

+

+// [70] EntityDecl ::= GEDecl | PEDecl

+EntityDecl = ({GEDecl} | {PEDecl})

+

+// [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'

+GEDecl = (<\!ENTITY{S}{Name}{S}{EntityDef}{S}?>)

+

+// [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'

+PEDecl = (<\!ENTITY{S}\%{S}{Name}{S}{PEDef}{S}?>)

+

+// [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)

+EntityDef = ({EntityValue} | ({ExternalID}{NDataDecl}?))

+

+// [74] PEDef ::= EntityValue | ExternalID

+PEDef = ({EntityValue} | {ExternalID})

+

+// [75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral 

+ExternalID = (SYSTEM{S}{SystemLiteral}|PUBLIC{S}{PubidLiteral}{S}{SystemLiteral} )

+

+// [76] NDataDecl ::= S 'NDATA' S Name

+NDataDecl = ({S}NDATA{S}{Name})

+

+// [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'

+TextDecl = (<\?xml{VersionInfo}?{EncodingDecl}{S}?\?>)

+

+// [78] extParsedEnt ::= TextDecl? content

+extParsedEnt = ({TextDecl}?{content})

+

+// [79] extPE ::= TextDecl? extSubsetDecl

+extPE = ({TextDecl}?{extSubsetDecl})

+

+// [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'" ) 

+EncodingDecl = ({S}encoding{S}*{Eq}{S}*(\"{EncName}\"|\'{EncName}\'))

+

+// [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*

+EncName = ([A-Za-z]([A-Za-z0-9._]|\-)*)

+

+// [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'

+NotationDecl = (<\!NOTATION{S}{Name}{S}({ExternalID}|{PublicID}){S}?>)

+

+// [83] PublicID ::= 'PUBLIC' S PubidLiteral

+PublicID = (PUBLIC{S}{PubidLiteral})

+

+// [84]  Letter ::= BaseChar | Ideographic

+Letter = ({BaseChar} | {Ideographic})

+

+// [85]  BaseChar ::= [#x0041-#x005A] | [#x0061-#x007A] | [#x00C0-#x00D6]

+// | [#x00D8-#x00F6] | [#x00F8-#x00FF] | [#x0100-#x0131]

+// | [#x0134-#x013E] | [#x0141-#x0148] | [#x014A-#x017E]

+// | [#x0180-#x01C3] | [#x01CD-#x01F0] | [#x01F4-#x01F5]

+// | [#x01FA-#x0217] | [#x0250-#x02A8] | [#x02BB-#x02C1] | #x0386

+// | [#x0388-#x038A] | #x038C | [#x038E-#x03A1] | [#x03A3-#x03CE]

+// | [#x03D0-#x03D6] | #x03DA | #x03DC | #x03DE | #x03E0

+// | [#x03E2-#x03F3] | [#x0401-#x040C] | [#x040E-#x044F]

+// | [#x0451-#x045C] | [#x045E-#x0481] | [#x0490-#x04C4]

+// | [#x04C7-#x04C8] | [#x04CB-#x04CC] | [#x04D0-#x04EB]

+// | [#x04EE-#x04F5] | [#x04F8-#x04F9] | [#x0531-#x0556] | #x0559

+// | [#x0561-#x0586] | [#x05D0-#x05EA] | [#x05F0-#x05F2]

+// | [#x0621-#x063A] | [#x0641-#x064A] | [#x0671-#x06B7]

+// | [#x06BA-#x06BE] | [#x06C0-#x06CE] | [#x06D0-#x06D3] | #x06D5

+// | [#x06E5-#x06E6] | [#x0905-#x0939] | #x093D | [#x0958-#x0961]

+// | [#x0985-#x098C] | [#x098F-#x0990] | [#x0993-#x09A8]

+// | [#x09AA-#x09B0] | #x09B2 | [#x09B6-#x09B9] | [#x09DC-#x09DD]

+// | [#x09DF-#x09E1] | [#x09F0-#x09F1] | [#x0A05-#x0A0A]

+// | [#x0A0F-#x0A10] | [#x0A13-#x0A28] | [#x0A2A-#x0A30]

+// | [#x0A32-#x0A33] | [#x0A35-#x0A36] | [#x0A38-#x0A39]

+// | [#x0A59-#x0A5C] | #x0A5E | [#x0A72-#x0A74] | [#x0A85-#x0A8B]

+// | #x0A8D | [#x0A8F-#x0A91] | [#x0A93-#x0AA8] | [#x0AAA-#x0AB0]

+// | [#x0AB2-#x0AB3] | [#x0AB5-#x0AB9] | #x0ABD | #x0AE0

+// | [#x0B05-#x0B0C] | [#x0B0F-#x0B10] | [#x0B13-#x0B28]

+// | [#x0B2A-#x0B30] | [#x0B32-#x0B33] | [#x0B36-#x0B39] | #x0B3D

+// | [#x0B5C-#x0B5D] | [#x0B5F-#x0B61] | [#x0B85-#x0B8A]

+// | [#x0B8E-#x0B90] | [#x0B92-#x0B95] | [#x0B99-#x0B9A] | #x0B9C

+// | [#x0B9E-#x0B9F] | [#x0BA3-#x0BA4] | [#x0BA8-#x0BAA]

+// | [#x0BAE-#x0BB5] | [#x0BB7-#x0BB9] | [#x0C05-#x0C0C]

+// | [#x0C0E-#x0C10] | [#x0C12-#x0C28] | [#x0C2A-#x0C33]

+// | [#x0C35-#x0C39] | [#x0C60-#x0C61] | [#x0C85-#x0C8C]

+// | [#x0C8E-#x0C90] | [#x0C92-#x0CA8] | [#x0CAA-#x0CB3]

+// | [#x0CB5-#x0CB9] | #x0CDE | [#x0CE0-#x0CE1] | [#x0D05-#x0D0C]

+// | [#x0D0E-#x0D10] | [#x0D12-#x0D28] | [#x0D2A-#x0D39]

+// | [#x0D60-#x0D61] | [#x0E01-#x0E2E] | #x0E30 | [#x0E32-#x0E33]

+// | [#x0E40-#x0E45] | [#x0E81-#x0E82] | #x0E84 | [#x0E87-#x0E88]

+// | #x0E8A | #x0E8D | [#x0E94-#x0E97] | [#x0E99-#x0E9F]

+// | [#x0EA1-#x0EA3] | #x0EA5 | #x0EA7 | [#x0EAA-#x0EAB]

+// | [#x0EAD-#x0EAE] | #x0EB0 | [#x0EB2-#x0EB3] | #x0EBD

+// | [#x0EC0-#x0EC4] | [#x0F40-#x0F47] | [#x0F49-#x0F69]

+// | [#x10A0-#x10C5] | [#x10D0-#x10F6] | #x1100 | [#x1102-#x1103]

+// | [#x1105-#x1107] | #x1109 | [#x110B-#x110C] | [#x110E-#x1112]

+// | #x113C | #x113E | #x1140 | #x114C | #x114E | #x1150

+// | [#x1154-#x1155] | #x1159 | [#x115F-#x1161] | #x1163 | #x1165

+// | #x1167 | #x1169 | [#x116D-#x116E] | [#x1172-#x1173] | #x1175

+// | #x119E | #x11A8 | #x11AB | [#x11AE-#x11AF] | [#x11B7-#x11B8]

+// | #x11BA | [#x11BC-#x11C2] | #x11EB | #x11F0 | #x11F9

+// | [#x1E00-#x1E9B] | [#x1EA0-#x1EF9] | [#x1F00-#x1F15]

+// | [#x1F18-#x1F1D] | [#x1F20-#x1F45] | [#x1F48-#x1F4D]

+// | [#x1F50-#x1F57] | #x1F59 | #x1F5B | #x1F5D | [#x1F5F-#x1F7D]

+// | [#x1F80-#x1FB4] | [#x1FB6-#x1FBC] | #x1FBE | [#x1FC2-#x1FC4]

+// | [#x1FC6-#x1FCC] | [#x1FD0-#x1FD3] | [#x1FD6-#x1FDB]

+// | [#x1FE0-#x1FEC] | [#x1FF2-#x1FF4] | [#x1FF6-#x1FFC] | #x2126

+// | [#x212A-#x212B] | #x212E | [#x2180-#x2182] | [#x3041-#x3094]

+// | [#x30A1-#x30FA] | [#x3105-#x312C] | [#xAC00-#xD7A3]

+BaseChar = [\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u0131\u0134-\u013E\u0141-\u0148\u014A-\u017E\u0180-\u01C3\u01CD-\u01F0\u01F4-\u01F5\u01FA-\u0217\u0250-\u02A8\u02BB-\u02C1\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03D6\u03DA\u03DC\u03DE\u03E0\u03E2-\u03F3\u0401-\u040C\u040E-\u044F\u0451-\u045C\u045E-\u0481\u0490-\u04C4\u04C7-\u04C8\u04CB-\u04CC\u04D0-\u04EB\u04EE-\u04F5\u04F8-\u04F9\u0531-\u0556\u0559\u0561-\u0586\u05D0-\u05EA\u05F0-\u05F2\u0621-\u063A\u0641-\u064A\u0671-\u06B7\u06BA-\u06BE\u06C0-\u06CE\u06D0-\u06D3\u06D5\u06E5-\u06E6\u0905-\u0939\u093D\u0958-\u0961\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8B\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AE0\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B36-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB5\u0BB7-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CDE\u0CE0-\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D60-\u0D61\u0E01-\u0E2E\u0E30\u0E32-\u0E33\u0E40-\u0E45\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EAE\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0F40-\u0F47\u0F49-\u0F69\u10A0-\u10C5\u10D0-\u10F6\u1100\u1102-\u1103\u1105-\u1107\u1109\u110B-\u110C\u110E-\u1112\u113C\u113E\u1140\u114C\u114E\u1150\u1154-\u1155\u1159\u115F-\u1161\u1163\u1165\u1167\u1169\u116D-\u116E\u1172-\u1173\u1175\u119E\u11A8\u11AB\u11AE-\u11AF\u11B7-\u11B8\u11BA\u11BC-\u11C2\u11EB\u11F0\u11F9\u1E00-\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2126\u212A-\u212B\u212E\u2180-\u2182\u3041-\u3094\u30A1-\u30FA\u3105-\u312C\uAC00-\uD7A3]

+

+// [86]  Ideographic ::= [#x4E00-#x9FA5] | #x3007 | [#x3021-#x3029]

+Ideographic = [\u4E00-\u9FA5\u3007\u3021-\u3029]

+

+// [87]      CombiningChar    ::=    [#x0300-#x0345]    | [#x0360-#x0361]

+// | [#x0483-#x0486]          | [#x0591-#x05A1]         | [#x05A3-#x05B9]

+// | [#x05BB-#x05BD]       | #x05BF       | [#x05C1-#x05C2]	 | #x05C4

+// | [#x064B-#x0652]    | #x0670    | [#x06D6-#x06DC]   | [#x06DD-#x06DF]

+// | [#x06E0-#x06E4]          | [#x06E7-#x06E8]         | [#x06EA-#x06ED]

+// | [#x0901-#x0903]       | #x093C       | [#x093E-#x094C]      | #x094D

+// | [#x0951-#x0954]    | [#x0962-#x0963]    | [#x0981-#x0983]   | #x09BC

+// | #x09BE       | #x09BF       | [#x09C0-#x09C4]      | [#x09C7-#x09C8]

+// | [#x09CB-#x09CD]   | #x09D7   | [#x09E2-#x09E3]   | #x0A02   | #x0A3C

+// | #x0A3E       | #x0A3F       | [#x0A40-#x0A42]      | [#x0A47-#x0A48]

+// | [#x0A4B-#x0A4D]    | [#x0A70-#x0A71]    | [#x0A81-#x0A83]   | #x0ABC

+// | [#x0ABE-#x0AC5]          | [#x0AC7-#x0AC9]         | [#x0ACB-#x0ACD]

+// | [#x0B01-#x0B03]    | #x0B3C    | [#x0B3E-#x0B43]   | [#x0B47-#x0B48]

+// | [#x0B4B-#x0B4D]          | [#x0B56-#x0B57]         | [#x0B82-#x0B83]

+// | [#x0BBE-#x0BC2]    | [#x0BC6-#x0BC8]    | [#x0BCA-#x0BCD]   | #x0BD7

+// | [#x0C01-#x0C03]          | [#x0C3E-#x0C44]         | [#x0C46-#x0C48]

+// | [#x0C4A-#x0C4D]          | [#x0C55-#x0C56]         | [#x0C82-#x0C83]

+// | [#x0CBE-#x0CC4]          | [#x0CC6-#x0CC8]         | [#x0CCA-#x0CCD]

+// | [#x0CD5-#x0CD6]          | [#x0D02-#x0D03]         | [#x0D3E-#x0D43]

+// | [#x0D46-#x0D48]       | [#x0D4A-#x0D4D]       | #x0D57      | #x0E31

+// | [#x0E34-#x0E3A]    | [#x0E47-#x0E4E]    | #x0EB1   | [#x0EB4-#x0EB9]

+// | [#x0EBB-#x0EBC]    | [#x0EC8-#x0ECD]    | [#x0F18-#x0F19]   | #x0F35

+// | #x0F37      | #x0F39     | #x0F3E     | #x0F3F     | [#x0F71-#x0F84]

+// | [#x0F86-#x0F8B]    | [#x0F90-#x0F95]    | #x0F97   | [#x0F99-#x0FAD]

+// | [#x0FB1-#x0FB7]       | #x0FB9       | [#x20D0-#x20DC]      | #x20E1

+// | [#x302A-#x302F] | #x3099 | #x309A

+CombiningChar =    [\u0300-\u0345\u0360-\u0361\u0483-\u0486\u0591-\u05A1\u05A3-\u05B9\u05BB-\u05BD\u05BF\u05C1-\u05C2\u05C4\u064B-\u0652\u0670\u06D6-\u06DC\u06DD-\u06DF\u06E0-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0901-\u0903\u093C\u093E-\u094C\u094D\u0951-\u0954\u0962-\u0963\u0981-\u0983\u09BC\u09BE\u09BF\u09C0-\u09C4\u09C7-\u09C8\u09CB-\u09CD\u09D7\u09E2-\u09E3\u0A02\u0A3C\u0A3E\u0A3F\u0A40-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A70-\u0A71\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0B01-\u0B03\u0B3C\u0B3E-\u0B43\u0B47-\u0B48\u0B4B-\u0B4D\u0B56-\u0B57\u0B82-\u0B83\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C01-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56\u0C82-\u0C83\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5-\u0CD6\u0D02-\u0D03\u0D3E-\u0D43\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86-\u0F8B\u0F90-\u0F95\u0F97\u0F99-\u0FAD\u0FB1-\u0FB7\u0FB9\u20D0-\u20DC\u20E1\u302A-\u302F\u3099\u309A]

+

+// [88]   Digit  ::=  [#x0030-#x0039] | [#x0660-#x0669] | [#x06F0-#x06F9]

+// | [#x0966-#x096F]          | [#x09E6-#x09EF]         | [#x0A66-#x0A6F]

+// | [#x0AE6-#x0AEF]          | [#x0B66-#x0B6F]         | [#x0BE7-#x0BEF]

+// | [#x0C66-#x0C6F]          | [#x0CE6-#x0CEF]         | [#x0D66-#x0D6F]

+// | [#x0E50-#x0E59] | [#x0ED0-#x0ED9] | [#x0F20-#x0F29]

+Digit =  [\u0030-\u0039\u0660-\u0669\u06F0-\u06F9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE7-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29]

+

+// [89]  Extender ::= #x00B7 | #x02D0 | #x02D1 | #x0387 | #x0640 | #x0E46

+// | #x0EC6       | #x3005       | [#x3031-#x3035]      | [#x309D-#x309E]

+// | [#x30FC-#x30FE]

+Extender = [\u00B7\u02D0\u02D1\u0387\u0640\u0E46\u0EC6\u3005\u3031-\u3035\u309D-\u309E\u30FC-\u30FE]

+

+

+

+/**

+ * JSP and scripting marker allowances

+ */

+

+jspCommentStart = <%--

+jspCommentEnd   = --%>

+

+jspScriptletStart        = <%

+jspExpressionStart       = {jspScriptletStart}=

+jspDeclarationStart      = {jspScriptletStart}\!

+jspScriptletEnd          = %>

+jspDirectiveStart        = {jspScriptletStart}@

+

+%%

+

+/* white space within a tag */

+<ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_ATTRIBUTE_VALUE, ST_JSP_ATTRIBUTE_VALUE, ST_PI, ST_XML_PI_EQUALS, ST_XML_PI_ATTRIBUTE_NAME, ST_XML_PI_ATTRIBUTE_VALUE, ST_XML_DECLARATION, ST_XML_DOCTYPE_DECLARATION, ST_XML_ELEMENT_DECLARATION, ST_XML_ATTLIST_DECLARATION, ST_XML_DECLARATION_CLOSE, ST_XML_DOCTYPE_ID_PUBLIC, ST_XML_DOCTYPE_ID_SYSTEM, ST_XML_DOCTYPE_EXTERNAL_ID, ST_JSP_DIRECTIVE_NAME, ST_JSP_DIRECTIVE_ATTRIBUTE_NAME, ST_JSP_DIRECTIVE_EQUALS, ST_JSP_DIRECTIVE_ATTRIBUTE_VALUE,ST_XML_ATTRIBUTE_VALUE_DQUOTED,ST_XML_ATTRIBUTE_VALUE_SQUOTED,ST_DHTML_ATTRIBUTE_NAME,ST_DHTML_EQUALS,ST_DHTML_ATTRIBUTE_VALUE,ST_DHTML_TAG_CLOSE> {S}* {

+	if(Debug.debugTokenizer)

+		dump("white space");//$NON-NLS-1$

+        return WHITE_SPACE;

+}

+

+// BEGIN REGULAR XML

+/* handle opening a new tag almost anywhere */

+

+

+<YYINITIAL, ST_XML_TAG_NAME, ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_DECLARATION, ST_JSP_DIRECTIVE_NAME, ST_JSP_DIRECTIVE_NAME_WHITESPACE, ST_JSP_DIRECTIVE_ATTRIBUTE_NAME, ST_JSP_DIRECTIVE_EQUALS, ST_JSP_DIRECTIVE_ATTRIBUTE_VALUE> {genericTagOpen} {

+	if(Debug.debugTokenizer)

+		dump("\nstart tag open");//$NON-NLS-1$

+	if (!fStateStack.empty() && fStateStack.peek()== ST_XML_COMMENT){

+		fStateStack.pop();

+		fEmbeddedHint = XML_COMMENT_TEXT;

+		yybegin(ST_XML_TAG_NAME);

+		String tagName = "";

+		assembleEmbeddedTagSequence(XML_TAG_OPEN, tagName); // ?

+		return PROXY_CONTEXT;

+	}

+	fEmbeddedHint = XML_TAG_NAME;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+        yybegin(ST_XML_TAG_NAME);

+        return XML_TAG_OPEN;

+}

+/* VERY special cases for tags as values */

+/* quoted JSP */

+<ST_XML_ATTRIBUTE_VALUE_DQUOTED> ["] {

+	return isJspTag()? JSP_TAG_ATTRIBUTE_VALUE_DQUOTE : XML_TAG_ATTRIBUTE_VALUE_DQUOTE;

+}

+<ST_XML_ATTRIBUTE_VALUE_SQUOTED> ['] {

+	return isJspTag() ? JSP_TAG_ATTRIBUTE_VALUE_SQUOTE : XML_TAG_ATTRIBUTE_VALUE_SQUOTE;

+}

+<ST_XML_ATTRIBUTE_VALUE, ST_JSP_ATTRIBUTE_VALUE> ["] {

+	String type = yy_lexical_state == ST_XML_ATTRIBUTE_VALUE ? XML_TAG_ATTRIBUTE_VALUE_DQUOTE : JSP_TAG_ATTRIBUTE_VALUE_DQUOTE;

+

+	if (Debug.debugTokenizer) {

+		System.out.println("begin embedded region: " + fEmbeddedHint+", "+type);//$NON-NLS-1$

+	}

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;

+	yybegin(ST_XML_ATTRIBUTE_VALUE_DQUOTED);

+	fStateStack.push(yystate());

+	if(Debug.debugTokenizer)

+		dump("JSP attribute value start - complex double quoted");//$NON-NLS-1$

+	assembleEmbeddedContainer(type, type);

+	fStateStack.pop();

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+	yybegin(ST_XML_ATTRIBUTE_NAME);

+	if (fEmbeddedContainer.getLastRegion().getType() == UNDEFINED) {

+		fProxyUnknownRegion = fRegionFactory.createToken(XML_TAG_ATTRIBUTE_VALUE, fEmbeddedContainer.getStart(), fEmbeddedContainer.getTextLength(), fEmbeddedContainer.getLength());

+		return PROXY_UNKNOWN_CONTEXT;

+	}

+	return PROXY_CONTEXT;

+}

+<ST_XML_ATTRIBUTE_VALUE, ST_JSP_ATTRIBUTE_VALUE> ['] {

+	String type = yy_lexical_state == ST_XML_ATTRIBUTE_VALUE ? XML_TAG_ATTRIBUTE_VALUE_SQUOTE : JSP_TAG_ATTRIBUTE_VALUE_SQUOTE;

+	if (Debug.debugTokenizer) {

+		System.out.println("begin embedded region: " + fEmbeddedHint+", "+type);//$NON-NLS-1$

+	}

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;

+	yybegin(ST_XML_ATTRIBUTE_VALUE_SQUOTED);

+	fStateStack.push(yystate());

+	if(Debug.debugTokenizer)

+		dump("JSP attribute value start - complex single quoted");//$NON-NLS-1$

+	assembleEmbeddedContainer(type, type);

+	fStateStack.pop();

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+        yybegin(ST_XML_ATTRIBUTE_NAME);

+    if (fEmbeddedContainer.getLastRegion().getType() == UNDEFINED) {

+		fProxyUnknownRegion = fRegionFactory.createToken(XML_TAG_ATTRIBUTE_VALUE, fEmbeddedContainer.getStart(), fEmbeddedContainer.getTextLength(), fEmbeddedContainer.getLength());

+		return PROXY_UNKNOWN_CONTEXT;

+	}

+	return PROXY_CONTEXT;

+}

+

+<ST_XML_ATTRIBUTE_VALUE_DQUOTED> ([^<"\x24\x23]+|[\x24\x23]{S}*)

+{

+	return XML_TAG_ATTRIBUTE_VALUE;

+}

+<ST_XML_ATTRIBUTE_VALUE_SQUOTED> ([^<'\x24\x23]+|[\x24\x23]{S}*)

+{

+	return XML_TAG_ATTRIBUTE_VALUE;

+}

+

+

+<ST_XML_ATTRIBUTE_VALUE_DQUOTED,ST_XML_ATTRIBUTE_VALUE_SQUOTED> {genericTagOpen} {

+	if (Debug.debugTokenizer) {

+		System.out.println("begin embedded region: " + fEmbeddedHint+", genericTagOpen");//$NON-NLS-1$

+	}

+	int incomingState = yystate();

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+	if(Debug.debugTokenizer)

+		dump("tag inside of JSP attribute value start");//$NON-NLS-1$

+	yybegin(ST_XML_TAG_NAME);

+	assembleEmbeddedContainer(XML_TAG_OPEN, new String[]{XML_TAG_CLOSE,XML_EMPTY_TAG_CLOSE});

+	if(yystate() != ST_ABORT_EMBEDDED)

+        yybegin(incomingState);

+	return PROXY_CONTEXT;

+}

+<ST_XML_ATTRIBUTE_VALUE_DQUOTED,ST_XML_ATTRIBUTE_VALUE_SQUOTED> {genericEndTagOpen} {

+	if (Debug.debugTokenizer) {

+		System.out.println("begin embedded region: " + fEmbeddedHint+", genericEndTagOpen");//$NON-NLS-1$

+	}

+	int incomingState = yystate();

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+	if(Debug.debugTokenizer)

+		dump("JSP attribute value start - end tag");//$NON-NLS-1$

+	yybegin(ST_XML_TAG_NAME);

+	assembleEmbeddedContainer(XML_END_TAG_OPEN, new String[]{XML_TAG_CLOSE,XML_EMPTY_TAG_CLOSE});

+	if(yystate() != ST_ABORT_EMBEDDED)

+        yybegin(incomingState);

+	return PROXY_CONTEXT;

+}

+

+/* unquoted */

+<ST_XML_ATTRIBUTE_VALUE> {genericTagOpen} {

+	if (Debug.debugTokenizer) {

+		System.out.println("begin embedded region: " + fEmbeddedHint+", unquoted genericTagOpen");//$NON-NLS-1$

+	}

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+	fStateStack.push(yystate());

+	if(Debug.debugTokenizer)

+		dump("JSP tag embedded name start - start tag");//$NON-NLS-1$

+	yybegin(ST_XML_TAG_NAME);

+	assembleEmbeddedContainer(XML_TAG_OPEN, new String[]{XML_TAG_CLOSE,XML_EMPTY_TAG_CLOSE});

+	fStateStack.pop();

+        yybegin(ST_XML_ATTRIBUTE_NAME);

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+	return PROXY_CONTEXT;

+}

+

+<YYINITIAL, ST_XML_TAG_NAME, ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_ATTRIBUTE_VALUE, ST_JSP_ATTRIBUTE_VALUE, ST_XML_DECLARATION> {genericEndTagOpen} {

+	if(Debug.debugTokenizer)

+		dump("\nend tag open");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_NAME;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+        yybegin(ST_XML_TAG_NAME);

+        return XML_END_TAG_OPEN;

+}

+/* specially treated JSP tag names */

+<ST_XML_TAG_NAME> jsp:root {

+	if(Debug.debugTokenizer)

+		dump("jsp:root tag name");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+        yybegin(ST_XML_ATTRIBUTE_NAME);

+        return JSP_ROOT_TAG_NAME;

+}

+<ST_XML_TAG_NAME> jsp:directive.(page|include|tag|taglib|attribute|variable) {

+	if(Debug.debugTokenizer)

+		dump("jsp directive tag name");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+        yybegin(ST_XML_ATTRIBUTE_NAME);

+        return JSP_DIRECTIVE_NAME;

+}

+/* the tag's name was found, start scanning for attributes */

+<ST_XML_TAG_NAME> {Name} {

+	if(Debug.debugTokenizer)

+		dump("tag name");//$NON-NLS-1$

+    String tagname = yytext();

+    boolean jspTag = tagname.indexOf(':') != -1;

+	if (fEmbeddedContainer != null) {

+    	fEmbeddedTag = jspTag;

+		fInTagEmbedded = true;

+    }

+	else {

+		fContainerTag = jspTag;

+		fInTagContainer = true;

+	}

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+        yybegin(ST_XML_ATTRIBUTE_NAME);

+        return XML_TAG_NAME;

+}

+

+/* another attribute name was found, resume looking for the equals sign */

+<ST_XML_ATTRIBUTE_NAME, ST_XML_EQUALS> {Name} {

+	if(Debug.debugTokenizer)

+		dump("attr name");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+        yybegin(ST_XML_EQUALS);

+        return XML_TAG_ATTRIBUTE_NAME;

+}

+/* an equal sign was found, what's next is the value */

+<ST_XML_EQUALS> {Eq} {

+	if(Debug.debugTokenizer)

+		dump("equals");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+        yybegin(isJspTag() ? ST_JSP_ATTRIBUTE_VALUE : ST_XML_ATTRIBUTE_VALUE);

+        return XML_TAG_ATTRIBUTE_EQUALS;

+}

+/* the value was found, look for the next name */

+<ST_XML_ATTRIBUTE_VALUE> {AttValue} { /* only allow for non-JSP tags for this does not obey JSP quoting rules */

+	if(Debug.debugTokenizer)

+		dump("attr value");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+        yybegin(ST_XML_ATTRIBUTE_NAME);

+        return XML_TAG_ATTRIBUTE_VALUE;

+}

+<ST_JSP_ATTRIBUTE_VALUE> {QuotedAttValue} { /* JSP attribute values have escape semantics */

+	if(Debug.debugTokenizer)

+		dump("jsp attr value");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+	yybegin(ST_XML_ATTRIBUTE_NAME);

+	return XML_TAG_ATTRIBUTE_VALUE;

+}

+

+/* the tag's close was found */

+<ST_XML_TAG_NAME, ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_ATTRIBUTE_VALUE, ST_JSP_ATTRIBUTE_VALUE> {genericTagClose} {

+	if(Debug.debugTokenizer)

+		dump("tag close");//$NON-NLS-1$

+	fEmbeddedHint = UNDEFINED;

+	if(isBlockMarker()) {

+		fEmbeddedHint = getBlockMarkerContext();

+		fEmbeddedPostState = ST_BLOCK_TAG_SCAN;

+        	yybegin(ST_BLOCK_TAG_SCAN);

+	}

+	else

+        	yybegin(YYINITIAL);

+

+	if (fEmbeddedContainer != null)

+		fInTagEmbedded = false;

+	else

+		fInTagContainer = false;

+

+	return XML_TAG_CLOSE;

+}

+/* the tag's close was found, but the tag doesn't need a matching end tag */

+<ST_XML_TAG_NAME, ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_ATTRIBUTE_VALUE, ST_JSP_ATTRIBUTE_VALUE> {genericEmptyTagClose} {

+        yybegin(YYINITIAL);

+	fEmbeddedHint = UNDEFINED;

+	if(Debug.debugTokenizer)

+		dump("empty tag close");//$NON-NLS-1$

+

+	if (fEmbeddedContainer != null)

+		fInTagEmbedded = false;

+	else

+		fInTagContainer = false;

+

+	return XML_EMPTY_TAG_CLOSE;

+}

+

+<ST_XML_TAG_NAME> [^</>\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u0131\u0134-\u013E\u0141-\u0148\u014A-\u017E\u0180-\u01C3\u01CD-\u01F0\u01F4-\u01F5\u01FA-\u0217\u0250-\u02A8\u02BB-\u02C1\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03D6\u03DA\u03DC\u03DE\u03E0\u03E2-\u03F3\u0401-\u040C\u040E-\u044F\u0451-\u045C\u045E-\u0481\u0490-\u04C4\u04C7-\u04C8\u04CB-\u04CC\u04D0-\u04EB\u04EE-\u04F5\u04F8-\u04F9\u0531-\u0556\u0559\u0561-\u0586\u05D0-\u05EA\u05F0-\u05F2\u0621-\u063A\u0641-\u064A\u0671-\u06B7\u06BA-\u06BE\u06C0-\u06CE\u06D0-\u06D3\u06D5\u06E5-\u06E6\u0905-\u0939\u093D\u0958-\u0961\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8B\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AE0\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B36-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB5\u0BB7-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CDE\u0CE0-\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D60-\u0D61\u0E01-\u0E2E\u0E30\u0E32-\u0E33\u0E40-\u0E45\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EAE\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0F40-\u0F47\u0F49-\u0F69\u10A0-\u10C5\u10D0-\u10F6\u1100\u1102-\u1103\u1105-\u1107\u1109\u110B-\u110C\u110E-\u1112\u113C\u113E\u1140\u114C\u114E\u1150\u1154-\u1155\u1159\u115F-\u1161\u1163\u1165\u1167\u1169\u116D-\u116E\u1172-\u1173\u1175\u119E\u11A8\u11AB\u11AE-\u11AF\u11B7-\u11B8\u11BA\u11BC-\u11C2\u11EB\u11F0\u11F9\u1E00-\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2126\u212A-\u212B\u212E\u2180-\u2182\u3041-\u3094\u30A1-\u30FA\u3105-\u312C\uAC00-\uD7A3\u4E00-\u9FA5\u3007\u3021-\u3029]* {

+	if(Debug.debugTokenizer)

+		dump("inappropriate tag name");//$NON-NLS-1$

+	if(!fStateStack.empty() && (fStateStack.peek()==ST_XML_ATTRIBUTE_VALUE_SQUOTED||fStateStack.peek()==ST_XML_ATTRIBUTE_VALUE_DQUOTED)) {

+		yybegin(ST_ABORT_EMBEDDED);

+		char c = yy_buffer[yy_markedPos - 1];

+		if (fStateStack.peek()==ST_XML_ATTRIBUTE_VALUE_DQUOTED && c == '\"') {

+			return isJspTag() ? JSP_TAG_ATTRIBUTE_VALUE_DQUOTE : XML_TAG_ATTRIBUTE_VALUE_DQUOTE;

+		}		

+		if (fStateStack.peek()==ST_XML_ATTRIBUTE_VALUE_SQUOTED && c == '\'') {

+			return isJspTag() ? JSP_TAG_ATTRIBUTE_VALUE_SQUOTE : XML_TAG_ATTRIBUTE_VALUE_SQUOTE;

+		}

+		yypushback(yylength()-1);

+		return XML_TAG_ATTRIBUTE_VALUE;

+	}

+	yybegin(YYINITIAL);

+        return XML_CONTENT;

+}

+

+// END REGULAR XML

+

+// BEGIN NESTED XML TAGS

+<ST_XML_ATTRIBUTE_NAME, ST_XML_EQUALS> <{Name} {

+	String tagName = yytext().substring(1);

+	// pushback to just after the opening bracket

+	yypushback(yylength() - 1);

+	/*

+	 * If this tag can not be nested or we're already searching for an

+	 * attribute name, equals, or value, return immediately.

+	 */

+	if (!isNestable(tagName) || (!fStateStack.empty() && (fStateStack.peek() == ST_XML_ATTRIBUTE_NAME || fStateStack.peek() == ST_XML_EQUALS || fStateStack.peek() == ST_XML_ATTRIBUTE_VALUE || fStateStack.peek() == ST_JSP_ATTRIBUTE_VALUE))) {

+		yybegin(ST_XML_TAG_NAME);

+		return XML_TAG_OPEN;

+	}

+	if(Debug.debugTokenizer)

+		dump("tag in place of attr name");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+	fStateStack.push(yystate());

+	// embedded container should be looking for the name (again) next

+	yybegin(ST_XML_TAG_NAME);

+	assembleEmbeddedTagSequence(XML_TAG_OPEN, tagName); // ?

+	fStateStack.pop();

+	yybegin(ST_XML_EQUALS);

+	return PROXY_CONTEXT;

+}

+<ST_XML_ATTRIBUTE_VALUE, ST_JSP_ATTRIBUTE_VALUE> <{Name} {

+	String tagName = yytext().substring(1);

+	// pushback to just after the opening bracket

+	yypushback(yylength() - 1);

+	/*

+	 * If this tag can not be nested or we're already searching for an

+	 * attribute name, equals, or value, return immediately.

+	 */

+	if (!isNestable(tagName) || (!fStateStack.empty() && (fStateStack.peek() == ST_XML_ATTRIBUTE_NAME || fStateStack.peek() == ST_XML_EQUALS || fStateStack.peek() == ST_XML_ATTRIBUTE_VALUE || fStateStack.peek() == ST_JSP_ATTRIBUTE_VALUE))) {

+		yybegin(ST_XML_TAG_NAME);

+		return XML_TAG_OPEN;

+	}

+	if(Debug.debugTokenizer)

+		dump("tag in place of attr value");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+	fStateStack.push(yystate());

+	// embedded container should be looking for the name (again) next

+	yybegin(ST_XML_TAG_NAME);

+	assembleEmbeddedTagSequence(XML_TAG_OPEN, tagName); // ?

+	fStateStack.pop();

+	yybegin(ST_XML_ATTRIBUTE_NAME);

+	return PROXY_CONTEXT;

+}

+// END NESTED XML

+

+// XML & JSP Comments

+

+<YYINITIAL, ST_XML_TAG_NAME, ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_ATTRIBUTE_VALUE, ST_JSP_ATTRIBUTE_VALUE, ST_XML_DECLARATION, ST_JSP_DIRECTIVE_NAME, ST_JSP_DIRECTIVE_NAME_WHITESPACE, ST_JSP_DIRECTIVE_ATTRIBUTE_NAME, ST_JSP_DIRECTIVE_EQUALS, ST_JSP_DIRECTIVE_ATTRIBUTE_VALUE> {CommentStart} {

+	if(Debug.debugTokenizer)

+		dump("\ncomment start");//$NON-NLS-1$

+	fEmbeddedHint = XML_COMMENT_TEXT;

+	fEmbeddedPostState = ST_XML_COMMENT;

+	yybegin(ST_XML_COMMENT);

+	return XML_COMMENT_OPEN;

+}

+<ST_XML_COMMENT> .|\r|\n {

+	if(Debug.debugTokenizer)

+		dump("comment content");//$NON-NLS-1$

+	return scanXMLCommentText();

+}

+

+<ST_XML_COMMENT_END> {CommentEnd} {

+	if(Debug.debugTokenizer)

+		dump("comment end");//$NON-NLS-1$

+	fEmbeddedHint = UNDEFINED;

+	yybegin(YYINITIAL);

+	return XML_COMMENT_CLOSE;

+}

+

+<ST_JSP_CONTENT> {jspScriptletEnd} {

+	if(Debug.debugTokenizer)

+		dump("JSP end");//$NON-NLS-1$

+	if (Debug.debugTokenizer) {

+		if(fStateStack.peek()!=YYINITIAL)

+			System.out.println("end embedded region");//$NON-NLS-1$

+	}

+	yybegin(fStateStack.pop());

+	return JSP_CLOSE;

+}

+<ST_JSP_CONTENT> .|\n|\r {

+	if(Debug.debugTokenizer)

+		dump("JSP code content");//$NON-NLS-1$

+	return doScan("%>", false, false, false, JSP_CONTENT, ST_JSP_CONTENT, ST_JSP_CONTENT);

+}

+{jspScriptletStart} {

+	/* JSP scriptlet begun (anywhere)

+	 * A consequence of the start anywhere possibility is that the

+	 *  incoming state must be checked to see if it's erroneous

+	 *  due to the order of precedence generated

+	 */

+	// begin sanity checks

+	if(yystate() == ST_JSP_CONTENT) {

+		// at the beginning?!

+		yypushback(1);

+		return JSP_CONTENT;

+	}

+	else if(yystate() == ST_BLOCK_TAG_SCAN) {

+		yypushback(2);

+		return doBlockTagScan();

+	}

+	else if(yystate() == ST_XML_COMMENT) {

+		yypushback(2);

+		return scanXMLCommentText();

+	}

+	else if(yystate() == ST_JSP_COMMENT) {

+		yypushback(2);

+		return scanJSPCommentText();

+	}

+	// finished sanity checks

+	fStateStack.push(yystate());

+	if(fStateStack.peek()==YYINITIAL) {

+		// the simple case, just a regular scriptlet out in content

+		if(Debug.debugTokenizer)

+			dump("\nJSP scriptlet start");//$NON-NLS-1$

+		yybegin(ST_JSP_CONTENT);

+		return JSP_SCRIPTLET_OPEN;

+	}

+	else {

+		if (Debug.debugTokenizer) {

+			System.out.println("begin embedded region: " + fEmbeddedHint+", jspScriptletStart");//$NON-NLS-1$

+		}

+		if(Debug.debugTokenizer)

+			dump("JSP scriptlet start");//$NON-NLS-1$

+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;

+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;

+		else if(yystate() == ST_CDATA_TEXT) {

+			fEmbeddedPostState = ST_CDATA_TEXT;

+			fEmbeddedHint = XML_CDATA_TEXT;

+		}

+		yybegin(ST_JSP_CONTENT);

+		assembleEmbeddedContainer(JSP_SCRIPTLET_OPEN, JSP_CLOSE);

+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {

+			yybegin(ST_BLOCK_TAG_SCAN);

+			return BLOCK_TEXT;

+		}

+		// required help for successive embedded regions

+		if(yystate() == ST_XML_TAG_NAME) {

+			fEmbeddedHint = XML_TAG_NAME;

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+		}

+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {

+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+			fEmbeddedPostState = ST_XML_EQUALS;

+		}

+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {

+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+		}

+        else if(yystate() == ST_JSP_ATTRIBUTE_VALUE) {

+            fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+            fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+        }

+		

+		return PROXY_CONTEXT;

+	}

+}

+{jspExpressionStart} {

+	/* JSP expression begun (anywhere)

+	 * A consequence of the start anywhere possibility is that the

+	 *  incoming state must be checked to see if it's erroneous

+	 *  due to the order of precedence generated

+	 */

+	// begin sanity checks

+	if(yystate() == ST_JSP_CONTENT) {

+		// at the beginning?!

+		yypushback(2);

+		return JSP_CONTENT;

+	}

+	else if(yystate() == ST_BLOCK_TAG_SCAN) {

+		yypushback(3);

+		return doBlockTagScan();

+	}

+	else if(yystate() == ST_XML_COMMENT) {

+		yypushback(3);

+		return scanXMLCommentText();

+	}

+	else if(yystate() == ST_JSP_COMMENT) {

+		yypushback(3);

+		return scanJSPCommentText();

+	}

+	// end sanity checks

+	fStateStack.push(yystate());

+	if(fStateStack.peek()==YYINITIAL) {

+		// the simple case, just an expression out in content

+		if(Debug.debugTokenizer)

+			dump("\nJSP expression start");//$NON-NLS-1$

+		yybegin(ST_JSP_CONTENT);

+		return JSP_EXPRESSION_OPEN;

+	}

+	else {

+		if (Debug.debugTokenizer) {

+			System.out.println("begin embedded region: " + fEmbeddedHint+", jspExpressionStart");//$NON-NLS-1$

+		}

+		if(Debug.debugTokenizer)

+			dump("JSP expression start");//$NON-NLS-1$

+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;

+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;

+		else if(yystate() == ST_CDATA_TEXT) {

+			fEmbeddedPostState = ST_CDATA_TEXT;

+			fEmbeddedHint = XML_CDATA_TEXT;

+		}

+		yybegin(ST_JSP_CONTENT);

+		assembleEmbeddedContainer(JSP_EXPRESSION_OPEN, JSP_CLOSE);

+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {

+			yybegin(ST_BLOCK_TAG_SCAN);

+			return BLOCK_TEXT;

+		}

+		// required help for successive embedded regions

+		if(yystate() == ST_XML_TAG_NAME) {

+			fEmbeddedHint = XML_TAG_NAME;

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+		}

+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {

+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+			fEmbeddedPostState = ST_XML_EQUALS;

+		}

+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {

+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+		}

+		else if(yystate() == ST_JSP_ATTRIBUTE_VALUE) {

+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+		}

+		

+		return PROXY_CONTEXT;

+	}

+}

+{jspDeclarationStart} {

+	/* JSP declaration begun (anywhere)

+	 * A consequence of the start anywhere possibility is that the

+	 *  incoming state must be checked to see if it's erroneous

+	 *  due to the order of precedence generated

+	 */

+	// begin sanity checks

+	if(yystate() == ST_JSP_CONTENT) {

+		// at the beginning?!

+		yypushback(2);

+		return JSP_CONTENT;

+	}

+	else if(yystate() == ST_BLOCK_TAG_SCAN) {

+		yypushback(3);

+		return doBlockTagScan();

+	}

+	else if(yystate() == ST_XML_COMMENT) {

+		yypushback(3);

+		return scanXMLCommentText();

+	}

+	else if(yystate() == ST_JSP_COMMENT) {

+		yypushback(3);

+		return scanJSPCommentText();

+	}

+	// end sanity checks

+	fStateStack.push(yystate());

+	if(fStateStack.peek()==YYINITIAL) {

+		// the simple case, just a declaration out in content

+		if(Debug.debugTokenizer)

+			dump("\nJSP declaration start");//$NON-NLS-1$

+		yybegin(ST_JSP_CONTENT);

+		return JSP_DECLARATION_OPEN;

+	}

+	else {

+		if (Debug.debugTokenizer) {

+			System.out.println("begin embedded region: " + fEmbeddedHint+", jspDeclarationStart");//$NON-NLS-1$

+		}

+		if(Debug.debugTokenizer)

+			dump("JSP declaration start");//$NON-NLS-1$

+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;

+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;

+		else if(yystate() == ST_CDATA_TEXT) {

+			fEmbeddedPostState = ST_CDATA_TEXT;

+			fEmbeddedHint = XML_CDATA_TEXT;

+		}

+		yybegin(ST_JSP_CONTENT);

+		assembleEmbeddedContainer(JSP_DECLARATION_OPEN, JSP_CLOSE);

+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {

+			yybegin(ST_BLOCK_TAG_SCAN);

+			return BLOCK_TEXT;

+		}

+		// required help for successive embedded regions

+		if(yystate() == ST_XML_TAG_NAME) {

+			fEmbeddedHint = XML_TAG_NAME;

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+		}

+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {

+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+			fEmbeddedPostState = ST_XML_EQUALS;

+		}

+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {

+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+		}

+		else if(yystate() == ST_JSP_ATTRIBUTE_VALUE) {

+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+		}

+		return PROXY_CONTEXT;

+	}

+}

+{jspCommentStart} {

+	/* JSP comment begun (anywhere)

+	 * A consequence of the start anywhere possibility is that the

+	 *  incoming state must be checked to see if it's erroneous

+	 *  due to the order of precedence generated

+	 */

+	// begin sanity checks

+	if(yystate() == ST_JSP_CONTENT) {

+		// at the beginning?!

+		yypushback(3);

+		return JSP_CONTENT;

+	}

+	else if(yystate() == ST_BLOCK_TAG_SCAN) {

+		yypushback(4);

+		return doBlockTagScan();

+	}

+	else if(yystate() == ST_XML_COMMENT) {

+		yypushback(4);

+		return scanXMLCommentText();

+	}

+	else if(yystate() == ST_JSP_COMMENT) {

+		yypushback(4);

+		return scanJSPCommentText();

+	}

+	else if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN)  {

+		yybegin(ST_JSP_COMMENT);

+		assembleEmbeddedContainer(JSP_COMMENT_OPEN, JSP_COMMENT_CLOSE);

+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN)

+			yybegin(ST_BLOCK_TAG_SCAN);

+		return PROXY_CONTEXT;

+	}

+	// finished sanity checks

+	if(yystate()==YYINITIAL) {

+		// the simple case, just a regular scriptlet out in content

+		if(Debug.debugTokenizer)

+			dump("\nJSP comment start");//$NON-NLS-1$

+		yybegin(ST_JSP_COMMENT);

+		return JSP_COMMENT_OPEN;

+	}

+	else {

+		if (Debug.debugTokenizer) {

+			System.out.println("begin embedded region: " + fEmbeddedHint+", jspCommentStart");//$NON-NLS-1$

+		}

+		if(Debug.debugTokenizer)

+			dump("JSP comment start");//$NON-NLS-1$

+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;

+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;

+		else if(yystate() == ST_CDATA_TEXT) {

+			fEmbeddedPostState = ST_CDATA_TEXT;

+			fEmbeddedHint = XML_CDATA_TEXT;

+		}

+		yybegin(ST_JSP_COMMENT);

+		// the comment container itself will act as comment text

+		fEmbeddedHint = JSP_COMMENT_TEXT;

+		assembleEmbeddedContainer(JSP_COMMENT_OPEN, JSP_COMMENT_CLOSE);

+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {

+			yybegin(ST_BLOCK_TAG_SCAN);

+			return BLOCK_TEXT;

+		}

+		/*

+		 * required help for successive embedded regions; mark this one as a

+		 * comment so it will be otherwise ignored but preserved (which is why

+		 * we can't use white-space)

+		 */

+		if(yystate() == ST_XML_TAG_NAME) {

+			fEmbeddedHint = XML_TAG_NAME;

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+		}

+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {

+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+			fEmbeddedPostState = ST_XML_EQUALS;

+		}

+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {

+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+		}

+		else if(yystate() == ST_JSP_ATTRIBUTE_VALUE) {

+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+		}

+		return PROXY_CONTEXT;

+	}

+}

+

+<ST_BLOCK_TAG_INTERNAL_SCAN> {jspCommentStart}  {

+	yybegin(ST_JSP_COMMENT);

+	assembleEmbeddedContainer(JSP_COMMENT_OPEN, JSP_COMMENT_CLOSE);

+	if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN)

+		yybegin(ST_BLOCK_TAG_SCAN);

+	return PROXY_CONTEXT;

+}

+

+{jspDirectiveStart} {

+	/* JSP directive begun (anywhere)

+	 * A consequence of the start anywhere possibility is that the

+	 *  incoming state must be checked to see if it's erroneous

+	 *  due to the order of precedence generated

+	 */

+	// begin sanity checks

+	if(yystate() == ST_JSP_CONTENT) {

+		// at the beginning?!

+		yypushback(2);

+		return JSP_CONTENT;

+	}

+	else if(yystate() == ST_BLOCK_TAG_SCAN) {

+		yypushback(3);

+		return doBlockTagScan();

+	}

+	else if(yystate() == ST_XML_COMMENT) {

+		yypushback(3);

+		return scanXMLCommentText();

+	}

+	else if(yystate() == ST_JSP_COMMENT) {

+		yypushback(3);

+		return scanJSPCommentText();

+	}

+	// end sanity checks

+	fStateStack.push(yystate());

+	if(fStateStack.peek()==YYINITIAL) {

+		// the simple case, just a declaration out in content

+		if(Debug.debugTokenizer)

+			dump("\nJSP directive start");//$NON-NLS-1$

+		yybegin(ST_JSP_DIRECTIVE_NAME);

+		return JSP_DIRECTIVE_OPEN;

+	}

+	else {

+		if (Debug.debugTokenizer) {

+			System.out.println("begin embedded region: " + fEmbeddedHint+", jspDirectiveStart");//$NON-NLS-1$

+		}

+		if(Debug.debugTokenizer)

+			dump("JSP declaration start");//$NON-NLS-1$

+		if(yystate() == ST_XML_ATTRIBUTE_VALUE_DQUOTED)

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_DQUOTED;

+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE_SQUOTED)

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_VALUE_SQUOTED;

+		else if(yystate() == ST_CDATA_TEXT) {

+			fEmbeddedPostState = ST_CDATA_TEXT;

+			fEmbeddedHint = XML_CDATA_TEXT;

+		}

+		yybegin(ST_JSP_DIRECTIVE_NAME);

+		assembleEmbeddedContainer(JSP_DIRECTIVE_OPEN, new String[]{JSP_DIRECTIVE_CLOSE, JSP_CLOSE});

+		if(yystate() == ST_BLOCK_TAG_INTERNAL_SCAN) {

+			yybegin(ST_BLOCK_TAG_SCAN);

+			return BLOCK_TEXT;

+		}

+		// required help for successive embedded regions

+		if(yystate() == ST_XML_TAG_NAME) {

+			fEmbeddedHint = XML_TAG_NAME;

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+		}

+		else if((yystate() == ST_XML_ATTRIBUTE_NAME || yystate() == ST_XML_EQUALS)) {

+			fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+			fEmbeddedPostState = ST_XML_EQUALS;

+		}

+		else if(yystate() == ST_XML_ATTRIBUTE_VALUE) {

+			fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+			fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+		}

+		return PROXY_CONTEXT;

+	}

+}

+

+

+<ST_JSP_DIRECTIVE_NAME> {Name} {

+	if(Debug.debugTokenizer)

+		dump("JSP directive name");//$NON-NLS-1$

+	yybegin(ST_JSP_DIRECTIVE_NAME_WHITESPACE);

+	return JSP_DIRECTIVE_NAME;

+}

+<ST_JSP_DIRECTIVE_NAME_WHITESPACE> {S}? {

+	if(Debug.debugTokenizer)

+		dump("white space");//$NON-NLS-1$

+	yybegin(ST_JSP_DIRECTIVE_ATTRIBUTE_NAME);

+	return WHITE_SPACE;

+}

+<ST_JSP_DIRECTIVE_ATTRIBUTE_NAME, ST_JSP_DIRECTIVE_EQUALS> {Name} {

+	if(Debug.debugTokenizer)

+		dump("attr name");//$NON-NLS-1$

+        yybegin(ST_JSP_DIRECTIVE_EQUALS);

+        return XML_TAG_ATTRIBUTE_NAME;

+}

+<ST_JSP_DIRECTIVE_EQUALS> {Eq} {

+	if(Debug.debugTokenizer)

+		dump("equals");//$NON-NLS-1$

+        yybegin(ST_JSP_DIRECTIVE_ATTRIBUTE_VALUE);

+        return XML_TAG_ATTRIBUTE_EQUALS;

+}

+<ST_JSP_DIRECTIVE_ATTRIBUTE_VALUE> {AttValue} {

+	if(Debug.debugTokenizer)

+		dump("attr value");//$NON-NLS-1$

+        yybegin(ST_JSP_DIRECTIVE_ATTRIBUTE_NAME);

+        return XML_TAG_ATTRIBUTE_VALUE;

+}

+<ST_JSP_DIRECTIVE_NAME, ST_JSP_DIRECTIVE_NAME_WHITESPACE, ST_JSP_DIRECTIVE_ATTRIBUTE_NAME, ST_JSP_DIRECTIVE_EQUALS, ST_JSP_DIRECTIVE_ATTRIBUTE_VALUE> {jspScriptletEnd} {

+	if(Debug.debugTokenizer)

+		dump("JSP end");//$NON-NLS-1$

+	if (Debug.debugTokenizer) {

+		if(fStateStack.peek()!=YYINITIAL)

+			System.out.println("end embedded region");//$NON-NLS-1$

+	}

+	yybegin(fStateStack.pop());

+	return JSP_DIRECTIVE_CLOSE;

+}

+

+<YYINITIAL> {jspCommentStart} {

+	if(Debug.debugTokenizer)

+		dump("\nJSP comment start");//$NON-NLS-1$

+	yybegin(ST_JSP_COMMENT);

+	return JSP_COMMENT_OPEN;

+}

+

+<ST_XML_ATTRIBUTE_VALUE_DQUOTED> \x24\x7b {

+	int enterState = yystate();

+	yybegin(ST_JSP_DQUOTED_EL);

+	assembleEmbeddedContainer(JSP_EL_OPEN, new String[]{JSP_EL_CLOSE, XML_TAG_ATTRIBUTE_VALUE_DQUOTE, JSP_TAG_ATTRIBUTE_VALUE_DQUOTE});

+	// abort early when an unescaped double quote is found in the EL

+	if(fEmbeddedContainer.getLastRegion().getType().equals(XML_TAG_ATTRIBUTE_VALUE_DQUOTE) || fEmbeddedContainer.getLastRegion().getType().equals(JSP_TAG_ATTRIBUTE_VALUE_DQUOTE)) {

+		yybegin(ST_ABORT_EMBEDDED);

+		fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+	}

+	else {

+		yybegin(enterState);

+	}

+	return PROXY_CONTEXT;

+}

+<ST_XML_ATTRIBUTE_VALUE_DQUOTED> \x23\x7b {

+	int enterState = yystate();

+	yybegin(ST_JSP_DQUOTED_VBL);

+	assembleEmbeddedContainer(JSP_VBL_OPEN, new String[]{JSP_VBL_CLOSE, XML_TAG_ATTRIBUTE_VALUE_DQUOTE, JSP_TAG_ATTRIBUTE_VALUE_DQUOTE});

+	// abort early when an unescaped double quote is found in the VBL

+	if(fEmbeddedContainer.getLastRegion().getType().equals(XML_TAG_ATTRIBUTE_VALUE_DQUOTE) || fEmbeddedContainer.getLastRegion().getType().equals(JSP_TAG_ATTRIBUTE_VALUE_DQUOTE)) {

+		yybegin(ST_ABORT_EMBEDDED);

+		fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+	}

+	else {

+		yybegin(enterState);

+	}

+	return PROXY_CONTEXT;

+}

+<ST_XML_ATTRIBUTE_VALUE_SQUOTED> \x24\x7b {

+	int enterState = yystate();

+	yybegin(ST_JSP_SQUOTED_EL);

+	assembleEmbeddedContainer(JSP_EL_OPEN, new String[]{JSP_EL_CLOSE, XML_TAG_ATTRIBUTE_VALUE_SQUOTE, JSP_TAG_ATTRIBUTE_VALUE_SQUOTE});

+	// abort early when an unescaped single quote is found in the EL

+	if(fEmbeddedContainer.getLastRegion().getType().equals(XML_TAG_ATTRIBUTE_VALUE_SQUOTE) || fEmbeddedContainer.getLastRegion().getType().equals(JSP_TAG_ATTRIBUTE_VALUE_SQUOTE)) {

+		yybegin(ST_ABORT_EMBEDDED);

+		fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+	}

+	else {

+		yybegin(enterState);

+	}

+	return PROXY_CONTEXT;

+}

+<ST_XML_ATTRIBUTE_VALUE_SQUOTED> \x23\x7b {

+	int enterState = yystate();

+	yybegin(ST_JSP_SQUOTED_VBL);

+	assembleEmbeddedContainer(JSP_VBL_OPEN, new String[]{JSP_VBL_CLOSE, XML_TAG_ATTRIBUTE_VALUE_SQUOTE, JSP_TAG_ATTRIBUTE_VALUE_SQUOTE});

+	// abort early when an unescaped single quote is found in the VBL

+	if(fEmbeddedContainer.getLastRegion().getType().equals(XML_TAG_ATTRIBUTE_VALUE_SQUOTE) || fEmbeddedContainer.getLastRegion().getType().equals(JSP_TAG_ATTRIBUTE_VALUE_SQUOTE)) {

+		yybegin(ST_ABORT_EMBEDDED);

+		fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+	}

+	else {

+		yybegin(enterState);

+	}

+	return PROXY_CONTEXT;

+}

+

+// unescaped double quote, return as ending region

+<ST_JSP_DQUOTED_EL,ST_JSP_DQUOTED_VBL> ["] {

+	return isJspTag() ? JSP_TAG_ATTRIBUTE_VALUE_DQUOTE: XML_TAG_ATTRIBUTE_VALUE_DQUOTE;

+}

+// unescaped single quote, return as ending region

+<ST_JSP_SQUOTED_EL,ST_JSP_SQUOTED_VBL> ['] {

+	return isJspTag() ? JSP_TAG_ATTRIBUTE_VALUE_SQUOTE : XML_TAG_ATTRIBUTE_VALUE_SQUOTE;

+}

+

+

+// paired escaped double quotes

+<ST_JSP_DQUOTED_EL> \\\" ([^\\]|\\[^"}]+)* \\\" {

+	return JSP_EL_QUOTED_CONTENT;

+}

+// everything else EL

+<ST_JSP_DQUOTED_EL> ([^\\}"]|\\[^"])+ {

+	return JSP_EL_CONTENT;

+}

+<ST_JSP_DQUOTED_EL> \\\" {

+	return JSP_EL_CONTENT;

+}

+// paired escaped quotes

+<ST_JSP_SQUOTED_EL> \\\' ([^\\]|\\[^'}]+)* \\\' {

+	return JSP_EL_QUOTED_CONTENT;

+}

+// everything else EL

+<ST_JSP_SQUOTED_EL> ([^\\}']|\\[^'])+ {

+	return JSP_EL_CONTENT;

+}

+<ST_JSP_SQUOTED_EL> \\\' {

+	return JSP_EL_CONTENT;

+}

+<ST_JSP_DQUOTED_EL,ST_JSP_SQUOTED_EL> } {

+	return JSP_EL_CLOSE;

+}

+

+

+// paired escaped quotes

+<ST_JSP_DQUOTED_VBL> \\\" ([^\\]|\\[^"}]+)* \\\" {

+	return JSP_VBL_QUOTED_CONTENT;

+}

+// everything else VBL

+<ST_JSP_DQUOTED_VBL> ([^\\}"]|\\[^"])+ {

+	return JSP_VBL_CONTENT;

+}

+<ST_JSP_DQUOTED_VBL> \\\" {

+	return JSP_VBL_CONTENT;

+}

+// paired escaped quotes

+<ST_JSP_SQUOTED_VBL> \\\' ([^\\]|\\[^'}]+)* \\\' {

+	return JSP_VBL_QUOTED_CONTENT;

+}

+// everything else VBL

+<ST_JSP_SQUOTED_VBL> ([^\\}']|\\[^'])+ {

+	return JSP_VBL_CONTENT;

+}

+<ST_JSP_SQUOTED_VBL> \\\' {

+	return JSP_VBL_CONTENT;

+}

+

+<ST_JSP_DQUOTED_VBL,ST_JSP_SQUOTED_VBL> } {

+	return JSP_VBL_CLOSE;

+}

+

+

+// XML content area EL

+<YYINITIAL> \x24\x7b[^\x7d]*/\x7d {

+	yybegin(ST_JSP_EL);

+	if(yylength() > 2)

+		yypushback(yylength() - 2);

+	fELlevel++;

+	fEmbeddedHint = XML_CONTENT;

+	fEmbeddedPostState = YYINITIAL;

+	assembleEmbeddedContainer(JSP_EL_OPEN, JSP_EL_CLOSE);

+	fEmbeddedHint = XML_CONTENT;

+	yybegin(YYINITIAL);

+	return PROXY_CONTEXT;

+}

+// XML attribute name EL

+<ST_XML_ATTRIBUTE_NAME> \x24\x7b[^\x7d]*/\x7d {

+	yybegin(ST_JSP_EL);

+	if(yylength() > 2)

+		yypushback(yylength() - 2);

+	fELlevel++;

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+	assembleEmbeddedContainer(JSP_EL_OPEN, JSP_EL_CLOSE);

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	yybegin(ST_XML_ATTRIBUTE_NAME);

+	return PROXY_CONTEXT;

+}

+<ST_JSP_EL> \x24\x7b {

+	fELlevel++;

+	if(fELlevel == 1) {

+		return JSP_EL_OPEN;

+	}

+}

+// XML content area VBL

+<YYINITIAL> \x23\x7b[^\x7d]*/\x7d {

+	yybegin(ST_JSP_VBL);

+	if(yylength() > 2)

+		yypushback(yylength() - 2);

+	fELlevel++;

+	fEmbeddedHint = XML_CONTENT;

+	fEmbeddedPostState = YYINITIAL;

+	assembleEmbeddedContainer(JSP_VBL_OPEN, JSP_VBL_CLOSE);

+	fEmbeddedHint = XML_CONTENT;

+	yybegin(YYINITIAL);

+	return PROXY_CONTEXT;

+}

+<ST_JSP_VBL> \x23\x7b {

+	fELlevel++;

+	if(fELlevel == 1) {

+		return JSP_VBL_OPEN;

+	}

+}

+// XML attribute name VBL

+<ST_XML_ATTRIBUTE_NAME> \x23\x7b[^\x7d]*/\x7d {

+	yybegin(ST_JSP_VBL);

+	if(yylength() > 2)

+		yypushback(yylength() - 2);

+	fELlevel++;

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+	assembleEmbeddedContainer(JSP_VBL_OPEN, JSP_VBL_CLOSE);

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	yybegin(ST_XML_ATTRIBUTE_NAME);

+	return PROXY_CONTEXT;

+}

+// return anything not starting quotes or ending the VBL as content

+<ST_JSP_VBL> [^\x7d\x22\x27]* {

+	return JSP_VBL_CONTENT;

+}

+// return anything not starting quotes or ending the EL as content

+<ST_JSP_EL> [^\x7d\x22\x27]* {

+	return JSP_EL_CONTENT;

+}

+

+

+// quotes

+<ST_JSP_EL> \x22 {

+	yybegin(ST_JSP_EL_DQUOTES);

+	return JSP_EL_DQUOTE;

+}

+<ST_JSP_EL_DQUOTES> \x22 {

+	yybegin(ST_JSP_EL);

+	return JSP_EL_DQUOTE;

+}

+<ST_JSP_EL_DQUOTES> [^\x22]+/\x22 {

+	yybegin(ST_JSP_EL_DQUOTES_END);

+	return JSP_EL_QUOTED_CONTENT;

+}

+<ST_JSP_EL_DQUOTES_END> \x22 {

+	yybegin(ST_JSP_EL);

+	return JSP_EL_DQUOTE;

+}

+<ST_JSP_EL> \x27 {

+	yybegin(ST_JSP_EL_SQUOTES);

+	return JSP_EL_SQUOTE;

+}

+<ST_JSP_EL_SQUOTES> \x27 {

+	yybegin(ST_JSP_EL);

+	return JSP_EL_SQUOTE;

+}

+<ST_JSP_EL_SQUOTES> [^\x27]+/\x27 {

+	yybegin(ST_JSP_EL_SQUOTES_END);

+	return JSP_EL_QUOTED_CONTENT;

+}

+<ST_JSP_EL_SQUOTES_END> \x27 {

+	yybegin(ST_JSP_EL);

+	return JSP_EL_SQUOTE;

+}

+// quotes

+<ST_JSP_VBL> \x22 {

+	yybegin(ST_JSP_VBL_DQUOTES);

+	return JSP_VBL_DQUOTE;

+}

+<ST_JSP_VBL_DQUOTES> \x22 {

+	yybegin(ST_JSP_VBL);

+	return JSP_VBL_DQUOTE;

+}

+<ST_JSP_VBL_DQUOTES> [^\x22]+/\x22 {

+	yybegin(ST_JSP_VBL_DQUOTES_END);

+	return JSP_VBL_QUOTED_CONTENT;

+}

+<ST_JSP_VBL_DQUOTES_END> \x22 {

+	yybegin(ST_JSP_VBL);

+	return JSP_VBL_DQUOTE;

+}

+<ST_JSP_VBL> \x27 {

+	yybegin(ST_JSP_VBL_SQUOTES);

+	return JSP_VBL_SQUOTE;

+}

+<ST_JSP_VBL_SQUOTES> \x27 {

+	yybegin(ST_JSP_VBL);

+	return JSP_VBL_SQUOTE;

+}

+<ST_JSP_VBL_SQUOTES> [^\x27]+/\x27 {

+	yybegin(ST_JSP_VBL_SQUOTES_END);

+	return JSP_VBL_QUOTED_CONTENT;

+}

+<ST_JSP_VBL_SQUOTES_END> \x27 {

+	yybegin(ST_JSP_VBL);

+	return JSP_VBL_SQUOTE;

+}

+

+// unquoted content

+<ST_JSP_EL> ([^}\x27\x22\x24]|\x24[^\x7b\x27\x22])+ {

+	//System.out.println(JSP_EL_CONTENT+ ":[" + yytext() + "]");

+	return JSP_EL_CONTENT;

+}

+<ST_JSP_EL> } {

+	fELlevel--;

+	if(fELlevel == 0) {

+		yybegin(YYINITIAL);

+		return JSP_EL_CLOSE;

+	}

+	return JSP_EL_CONTENT;

+}

+<ST_JSP_VBL> } {

+	fELlevel--;

+	if(fELlevel == 0) {

+		yybegin(YYINITIAL);

+		return JSP_VBL_CLOSE;

+	}

+	return JSP_VBL_CONTENT;

+}

+// EL unquoted in tag (section 2.1 declares it as valid in template text (XML_CONTENT) or attribute values

+<ST_XML_ATTRIBUTE_VALUE, ST_JSP_ATTRIBUTE_VALUE> \x24\x7b[^\x7d]+/\x7d {

+	if (Debug.debugTokenizer) {

+		System.out.println("begin embedded region: " + fEmbeddedHint+", el-unquoted");//$NON-NLS-1$

+	}

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+	fStateStack.push(yystate());

+	if(yylength() > 2)

+		yypushback(yylength() -2);

+	if(Debug.debugTokenizer)

+		dump("EL in attr value");//$NON-NLS-1$

+	yybegin(ST_JSP_EL);

+	fELlevel++;

+	assembleEmbeddedContainer(JSP_EL_OPEN, new String[]{JSP_EL_CLOSE});

+	fStateStack.pop();

+	yybegin(ST_XML_ATTRIBUTE_NAME);

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+	return PROXY_CONTEXT;

+}

+// VBL unquoted in tag or attribute values

+<ST_XML_ATTRIBUTE_VALUE, ST_JSP_ATTRIBUTE_VALUE> \x23\x7b[^\x7d]+/\x7d {

+	if (Debug.debugTokenizer) {

+		System.out.println("begin embedded region: " + fEmbeddedHint+", el-unquoted");//$NON-NLS-1$

+	}

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+	fStateStack.push(yystate());

+	if(yylength() > 2)

+		yypushback(yylength() -2);

+	if(Debug.debugTokenizer)

+		dump("VBL in attr value");//$NON-NLS-1$

+	yybegin(ST_JSP_VBL);

+	fELlevel++;

+	assembleEmbeddedContainer(JSP_VBL_OPEN, new String[]{JSP_VBL_CLOSE});

+	fStateStack.pop();

+	yybegin(ST_XML_ATTRIBUTE_NAME);

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+	return PROXY_CONTEXT;

+}

+

+<ST_JSP_COMMENT> .|\r|\n {

+	if(Debug.debugTokenizer)

+		dump("\nJSP comment text");//$NON-NLS-1$

+	return scanJSPCommentText();

+}

+<ST_JSP_COMMENT_END> {jspCommentEnd} {

+	if(Debug.debugTokenizer)

+		dump("\nJSP comment close");//$NON-NLS-1$

+	yybegin(YYINITIAL);

+	return JSP_COMMENT_CLOSE;

+}

+

+// XML misc

+

+{CDStart} {

+	if(Debug.debugTokenizer)

+		dump("\nCDATA start");//$NON-NLS-1$

+	fStateStack.push(yystate());

+	yybegin(ST_CDATA_TEXT);

+	return XML_CDATA_OPEN;

+}

+<ST_CDATA_TEXT> .|\r|\n {

+	if(Debug.debugTokenizer)

+		dump("CDATA text");//$NON-NLS-1$

+	fEmbeddedPostState = ST_CDATA_TEXT;

+	fEmbeddedHint = XML_CDATA_TEXT;

+	String returnedContext = doScan("]]>", false, true, true, XML_CDATA_TEXT, ST_CDATA_END,  ST_CDATA_END);//$NON-NLS-1$

+	if(returnedContext == XML_CDATA_TEXT)

+		yybegin(ST_CDATA_END);

+	return returnedContext;

+}

+<ST_CDATA_END> {CDEnd} {

+	if(Debug.debugTokenizer)

+		dump("CDATA end");//$NON-NLS-1$

+	yybegin(fStateStack.pop());

+	return XML_CDATA_CLOSE;

+}

+

+<YYINITIAL> {PEReference} {

+	if(Debug.debugTokenizer)

+		dump("\nPEReference");//$NON-NLS-1$

+	return XML_PE_REFERENCE;

+}

+<YYINITIAL> {CharRef} {

+	if(Debug.debugTokenizer)

+		dump("\nCharRef");//$NON-NLS-1$

+	return XML_CHAR_REFERENCE;

+}

+<YYINITIAL> {EntityRef} {

+	if(Debug.debugTokenizer)

+		dump("\nEntityRef");//$NON-NLS-1$

+	return XML_ENTITY_REFERENCE;

+}

+

+<YYINITIAL> {PIstart} {

+	if(Debug.debugTokenizer)

+		dump("\nprocessing instruction start");//$NON-NLS-1$

+	yybegin(ST_PI);

+        return XML_PI_OPEN;

+}

+// the next four are order dependent

+<ST_PI> ((X|x)(M|m)(L|l)) {

+	if(Debug.debugTokenizer)

+		dump("XML processing instruction target");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);

+        return XML_TAG_NAME;

+}

+<ST_PI> ([iI][mM][pP][oO][rR][tT]) {

+	if(Debug.debugTokenizer)

+		dump("DHTML processing instruction target");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+        yybegin(ST_DHTML_ATTRIBUTE_NAME);

+        return XML_TAG_NAME;

+}

+<ST_PI> xml-stylesheet {

+	if(Debug.debugTokenizer)

+		dump("XSL processing instruction target");//$NON-NLS-1$

+	fEmbeddedPostState = ST_XML_EQUALS;

+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);

+        return XML_TAG_NAME;

+}

+<ST_PI> {Name} {

+	if(Debug.debugTokenizer)

+		dump("processing instruction target");//$NON-NLS-1$

+	fEmbeddedHint = XML_CONTENT;

+        yybegin(ST_PI_WS);

+        return XML_TAG_NAME;

+}

+<ST_PI_WS> {S}+ {

+        yybegin(ST_PI_CONTENT);

+        return WHITE_SPACE;

+}

+<ST_PI, ST_PI_WS> \?> {

+	if(Debug.debugTokenizer)

+		dump("processing instruction end");//$NON-NLS-1$

+	fEmbeddedHint = UNDEFINED;

+        yybegin(YYINITIAL);

+        return XML_PI_CLOSE;

+}

+<ST_PI_CONTENT> . {

+		// block scan until close is found

+	return doScan("?>", false, false, false, XML_PI_CONTENT, ST_XML_PI_TAG_CLOSE, ST_XML_PI_TAG_CLOSE);

+}

+<ST_PI_CONTENT,ST_XML_PI_TAG_CLOSE> \?> {

+		// ended with nothing inside

+		fEmbeddedHint = UNDEFINED;

+        yybegin(YYINITIAL);

+        return XML_PI_CLOSE;

+}

+

+<ST_XML_PI_ATTRIBUTE_NAME, ST_XML_PI_EQUALS> {Name} {

+	if(Debug.debugTokenizer)

+		dump("XML processing instruction attribute name");//$NON-NLS-1$

+        yybegin(ST_XML_PI_EQUALS);

+        return XML_TAG_ATTRIBUTE_NAME;

+}

+<ST_XML_PI_EQUALS> {Eq} {

+	if(Debug.debugTokenizer)

+		dump("XML processing instruction '='");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+        yybegin(ST_XML_PI_ATTRIBUTE_VALUE);

+        return XML_TAG_ATTRIBUTE_EQUALS;

+}

+/* the value was found, look for the next name */

+<ST_XML_PI_ATTRIBUTE_VALUE> {AttValue} {

+	if(Debug.debugTokenizer)

+		dump("XML processing instruction attribute value");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);

+        return XML_TAG_ATTRIBUTE_VALUE;

+}

+/* the PI's close was found */

+<ST_XML_PI_EQUALS, ST_XML_PI_ATTRIBUTE_NAME, ST_XML_PI_ATTRIBUTE_VALUE> {PIend} {

+	if(Debug.debugTokenizer)

+		dump("XML processing instruction end");//$NON-NLS-1$

+	fEmbeddedHint = UNDEFINED;

+        yybegin(YYINITIAL);

+        return XML_PI_CLOSE;

+}

+// DHTML

+<ST_DHTML_ATTRIBUTE_NAME, ST_DHTML_EQUALS> {Name} {

+	if(Debug.debugTokenizer)

+		dump("DHTML processing instruction attribute name");//$NON-NLS-1$

+        yybegin(ST_DHTML_EQUALS);

+        return XML_TAG_ATTRIBUTE_NAME;

+}

+<ST_DHTML_EQUALS> {Eq} {

+	if(Debug.debugTokenizer)

+		dump("DHTML processing instruction '='");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_VALUE;

+	fEmbeddedPostState = ST_XML_ATTRIBUTE_NAME;

+        yybegin(ST_DHTML_ATTRIBUTE_VALUE);

+        return XML_TAG_ATTRIBUTE_EQUALS;

+}

+/* the value was found, look for the next name */

+<ST_DHTML_ATTRIBUTE_VALUE> {AttValue} | ([\'\"]([^\'\"\040\011\012\015<>/]|\/+[^\'\"\040\011\012\015<>/] )* ) {

+	if(Debug.debugTokenizer)

+		dump("DHTML processing instruction attribute value");//$NON-NLS-1$

+	fEmbeddedHint = XML_TAG_ATTRIBUTE_NAME;

+	fEmbeddedPostState = ST_XML_EQUALS;

+        yybegin(ST_DHTML_ATTRIBUTE_NAME);

+        return XML_TAG_ATTRIBUTE_VALUE;

+}

+/* The DHTML PI's close was found */

+<ST_DHTML_EQUALS, ST_DHTML_ATTRIBUTE_NAME, ST_DHTML_ATTRIBUTE_VALUE> [/]*> {

+	if(Debug.debugTokenizer)

+		dump("DHTML processing instruction end");//$NON-NLS-1$

+	fEmbeddedHint = UNDEFINED;

+        yybegin(YYINITIAL);

+        return XML_PI_CLOSE;

+}

+

+// XML declarations

+

+<YYINITIAL, ST_XML_TAG_NAME, ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_ATTRIBUTE_VALUE, ST_JSP_ATTRIBUTE_VALUE> {genericTagOpen}! {

+	fStateStack.push(yystate());

+	if(Debug.debugTokenizer)

+		dump("\ndeclaration start");//$NON-NLS-1$

+        yybegin(ST_XML_DECLARATION);

+	return XML_DECLARATION_OPEN;

+}

+<ST_XML_DECLARATION> [Ee][Ll][Ee][Mm][Ee][Nn][Tt] {

+	if(Debug.debugTokenizer)

+		dump("element");//$NON-NLS-1$

+	yybegin(ST_XML_ELEMENT_DECLARATION);

+	return XML_ELEMENT_DECLARATION;

+}

+<ST_XML_DECLARATION> [Dd][Oo][Cc][Tt][Yy][Pp][Ee] {

+	if(Debug.debugTokenizer)

+		dump("doctype");//$NON-NLS-1$

+	yybegin(ST_XML_DOCTYPE_DECLARATION);

+	return XML_DOCTYPE_DECLARATION;

+}

+<ST_XML_DECLARATION> [Aa][Tt][Tt][Ll][Ii][Ss][Tt] {

+	if(Debug.debugTokenizer)

+		dump("attlist");//$NON-NLS-1$

+	yybegin(ST_XML_ATTLIST_DECLARATION);

+	return XML_ATTLIST_DECLARATION;

+}

+

+// begin DOCTYPE handling procedure

+<ST_XML_DOCTYPE_DECLARATION, ST_XML_DOCTYPE_EXTERNAL_ID, ST_XML_DOCTYPE_ID_SYSTEM, ST_XML_DOCTYPE_ID_PUBLIC, ST_XML_DECLARATION_CLOSE> \[[^\]]*\] {

+	return XML_DOCTYPE_INTERNAL_SUBSET;

+}

+

+<ST_XML_DOCTYPE_DECLARATION> {Name} {

+	if(Debug.debugTokenizer)

+		dump("doctype type");//$NON-NLS-1$

+	yybegin(ST_XML_DOCTYPE_EXTERNAL_ID);

+	return XML_DOCTYPE_NAME;

+}

+<ST_XML_DOCTYPE_EXTERNAL_ID> [Pp][Uu][Bb][Ll][Ii][Cc] {

+	if(Debug.debugTokenizer)

+		dump("doctype external id");//$NON-NLS-1$

+	fEmbeddedHint = XML_DOCTYPE_EXTERNAL_ID_PUBREF;

+	yybegin(ST_XML_DOCTYPE_ID_PUBLIC);

+	return XML_DOCTYPE_EXTERNAL_ID_PUBLIC;

+}

+<ST_XML_DOCTYPE_EXTERNAL_ID> [Ss][Yy][Ss][Tt][Ee][Mm] {

+	if(Debug.debugTokenizer)

+		dump("doctype external id");//$NON-NLS-1$

+	fEmbeddedHint = XML_DOCTYPE_EXTERNAL_ID_SYSREF;

+	yybegin(ST_XML_DOCTYPE_ID_SYSTEM);

+	return XML_DOCTYPE_EXTERNAL_ID_SYSTEM;

+}

+<ST_XML_DOCTYPE_ID_PUBLIC> {AttValue}|{PubidLiteral} {

+	if(Debug.debugTokenizer)

+		dump("doctype public reference");//$NON-NLS-1$

+	fEmbeddedHint = UNDEFINED;

+	fEmbeddedPostState = YYINITIAL;

+	yybegin(ST_XML_DOCTYPE_ID_SYSTEM);

+	return XML_DOCTYPE_EXTERNAL_ID_PUBREF;

+}

+<ST_XML_DOCTYPE_ID_SYSTEM> {AttValue}|{SystemLiteral} {

+	if(Debug.debugTokenizer)

+		dump("doctype system reference");//$NON-NLS-1$

+	fEmbeddedHint = UNDEFINED;

+	fEmbeddedPostState = YYINITIAL;

+	yybegin(ST_XML_DECLARATION_CLOSE);

+	return XML_DOCTYPE_EXTERNAL_ID_SYSREF;

+}

+// end DOCTYPE handling

+

+// begin ELEMENT handling procedure

+<ST_XML_ELEMENT_DECLARATION> {AttValue}|{PubidLiteral} {

+	if(Debug.debugTokenizer)

+		dump("elementdecl name");//$NON-NLS-1$

+	fEmbeddedHint = UNDEFINED;

+	fEmbeddedPostState = YYINITIAL;

+	yybegin(ST_XML_ELEMENT_DECLARATION_CONTENT);

+	return XML_ELEMENT_DECL_NAME;

+}

+<ST_XML_ELEMENT_DECLARATION_CONTENT> [^>]* {

+	if(Debug.debugTokenizer)

+		dump("elementdecl contentspec");//$NON-NLS-1$

+	return XML_ELEMENT_DECL_CONTENT;

+}

+

+<ST_XML_ELEMENT_DECLARATION_CONTENT> {genericTagClose} {

+	if(Debug.debugTokenizer)

+		dump("elementdecl close");//$NON-NLS-1$

+	if (Debug.debugTokenizer) {

+		if(fStateStack.peek()!=YYINITIAL)

+			System.out.println("end embedded region");//$NON-NLS-1$

+	}

+	yybegin(fStateStack.pop());

+	return XML_DECLARATION_CLOSE;

+}

+// end ELEMENT handling

+

+// begin ATTLIST handling procedure

+<ST_XML_ATTLIST_DECLARATION> {AttValue}|{PubidLiteral} {

+	if(Debug.debugTokenizer)

+		dump("attlist name");//$NON-NLS-1$

+	fEmbeddedHint = UNDEFINED;

+	fEmbeddedPostState = YYINITIAL;

+	yybegin(ST_XML_ATTLIST_DECLARATION_CONTENT);

+	return XML_ATTLIST_DECL_NAME;

+}

+<ST_XML_ATTLIST_DECLARATION_CONTENT> [^>]* {

+	if(Debug.debugTokenizer)

+		dump("attlist contentspec");//$NON-NLS-1$

+	return XML_ATTLIST_DECL_CONTENT;

+}

+

+<ST_XML_ATTLIST_DECLARATION_CONTENT> {genericTagClose} {

+	if(Debug.debugTokenizer)

+		dump("attlist close");//$NON-NLS-1$

+	if (Debug.debugTokenizer) {

+		if(fStateStack.peek()!=YYINITIAL)

+			System.out.println("end embedded region");//$NON-NLS-1$

+	}

+	yybegin(fStateStack.pop());

+	return XML_DECLARATION_CLOSE;

+}

+// end ATTLIST handling

+

+<ST_XML_DECLARATION, ST_XML_DOCTYPE_DECLARATION, ST_XML_DOCTYPE_EXTERNAL_ID, ST_XML_ATTLIST_DECLARATION, ST_XML_ELEMENT_DECLARATION, ST_XML_DECLARATION_CLOSE, ST_XML_DOCTYPE_ID_PUBLIC, ST_XML_DOCTYPE_ID_SYSTEM, ST_XML_DOCTYPE_EXTERNAL_ID> {genericTagClose} {

+	if(Debug.debugTokenizer)

+		dump("declaration end");//$NON-NLS-1$

+	if (Debug.debugTokenizer) {

+		if(fStateStack.peek()!=YYINITIAL)

+			System.out.println("end embedded region");//$NON-NLS-1$

+	}

+	yybegin(fStateStack.pop());

+	return XML_DECLARATION_CLOSE;

+}

+// end DECLARATION handling

+

+<YYINITIAL> ([^<&%\x24\x23]*|\x23+|\x24+|[&%]{S}+{Name}[^&%<]*|[\x24\x23][^\x7b<&%][^<&%\x24\x23]*|\\[\x24\x23][\x7b]|[&%]{Name}([^;&%<]*|{S}+;*)) {

+	if(Debug.debugTokenizer)

+		dump("\nXML content");//$NON-NLS-1$

+	return XML_CONTENT;

+}

+

+<YYINITIAL> (%)+ {

+	if(Debug.debugTokenizer)

+		dump("non-reference %");//$NON-NLS-1$

+	return XML_CONTENT;

+}

+

+<ST_BLOCK_TAG_SCAN> .|\r|\n {

+		return doBlockTagScan();

+	}

+

+. {

+	if (Debug.debugTokenizer)

+		System.out.println("!!!unexpected!!!: \"" + yytext() + "\":" + //$NON-NLS-2$//$NON-NLS-1$

+			yychar + "-" + (yychar + yylength()));//$NON-NLS-1$

+	return UNDEFINED;

+}

+

+\040 {

+	if(Debug.debugTokenizer)

+		dump("SPACE");//$NON-NLS-1$

+	return WHITE_SPACE;

+}

+\011 {

+	if(Debug.debugTokenizer)

+		dump("0x9");//$NON-NLS-1$

+	return WHITE_SPACE;

+}

+\015 

+{

+	if(Debug.debugTokenizer)

+		dump("CARRIAGE RETURN");//$NON-NLS-1$

+	return WHITE_SPACE;

+}

+\012 {

+	if(Debug.debugTokenizer)

+		dump("LINE FEED");//$NON-NLS-1$

+	return WHITE_SPACE;

+}

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/XMLTokenizer.java b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/XMLTokenizer.java
new file mode 100644
index 0000000..b4607a2
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/XMLTokenizer.java
@@ -0,0 +1,1937 @@
+/* The following code was generated by JFlex 1.2.2 on 10/17/07 4:27 AM */
+
+/*******************************************************************************
+ * Copyright (c) 2004, 2007 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.wst.xml.core.internal.parser;
+
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockTokenizer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.xml.core.internal.Logger;
+import org.eclipse.wst.xml.core.internal.parser.regions.XMLParserRegionFactory;
+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
+
+
+/**
+ * This class is a scanner generated by 
+ * <a href="http://www.informatik.tu-muenchen.de/~kleing/jflex/">JFlex</a> 1.2.2
+ * on 10/17/07 4:27 AM from the specification file
+ * <tt>file:/D:/eclipse.wtp/workspace/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/XMLTokenizer.jflex</tt>
+ */
+public class XMLTokenizer implements BlockTokenizer, DOMRegionContext {
+
+  /** this character denotes the end of file */
+  final public static int YYEOF = -1;
+
+  /** lexical states */
+  final public static int ST_XML_DOCTYPE_EXTERNAL_ID = 23;
+  final public static int ST_XML_ELEMENT_DECLARATION_CONTENT = 27;
+  final public static int ST_DHTML_ATTRIBUTE_NAME = 12;
+  final public static int ST_XML_PI_TAG_CLOSE = 11;
+  final public static int ST_XML_DECLARATION_CLOSE = 21;
+  final public static int ST_XML_PI_ATTRIBUTE_VALUE = 10;
+  final public static int ST_DHTML_EQUALS = 13;
+  final public static int ST_XML_TAG_NAME = 16;
+  final public static int ST_XML_ATTRIBUTE_VALUE = 19;
+  final public static int ST_DHTML_ATTRIBUTE_VALUE = 14;
+  final public static int ST_XML_DOCTYPE_ID_SYSTEM = 25;
+  final public static int ST_XML_ATTRIBUTE_NAME = 17;
+  final public static int ST_XML_ELEMENT_DECLARATION = 26;
+  final public static int ST_XML_DOCTYPE_DECLARATION = 22;
+  final public static int ST_XML_ATTLIST_DECLARATION = 28;
+  final public static int ST_XML_COMMENT_END = 4;
+  final public static int ST_CDATA_TEXT = 1;
+  final public static int ST_DHTML_TAG_CLOSE = 15;
+  final public static int ST_XML_COMMENT = 3;
+  final public static int ST_PI_CONTENT = 7;
+  final public static int ST_PI_WS = 6;
+  final public static int ST_CDATA_END = 2;
+  final public static int ST_XML_ATTLIST_DECLARATION_CONTENT = 29;
+  final public static int ST_BLOCK_TAG_SCAN = 30;
+  final public static int ST_XML_PI_EQUALS = 9;
+  final public static int ST_XML_DECLARATION = 20;
+  final public static int YYINITIAL = 0;
+  final public static int ST_XML_DOCTYPE_ID_PUBLIC = 24;
+  final public static int ST_XML_EQUALS = 18;
+  final public static int ST_PI = 5;
+  final public static int ST_XML_PI_ATTRIBUTE_NAME = 8;
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static String yycmap_packed = 
+    "\11\0\1\5\1\22\2\0\1\14\22\0\1\14\1\21\1\11\1\55"+
+    "\1\16\1\17\1\12\1\13\1\16\1\16\1\16\1\16\1\16\1\7"+
+    "\1\6\1\3\12\15\1\10\1\61\1\1\1\45\1\2\1\4\1\16"+
+    "\1\34\1\62\1\32\1\33\1\50\1\57\1\36\1\36\1\42\1\36"+
+    "\1\36\1\27\1\25\1\44\1\43\1\47\1\36\1\40\1\56\1\35"+
+    "\1\60\2\36\1\23\1\46\1\36\1\31\1\0\1\20\1\0\1\10"+
+    "\1\0\1\52\1\62\1\63\1\53\1\37\1\57\1\36\1\66\1\42"+
+    "\2\36\1\30\1\26\1\44\1\43\1\47\1\36\1\40\1\41\1\51"+
+    "\1\60\1\36\1\36\1\24\1\54\1\36\1\0\1\0\72\0\1\65"+
+    "\10\0\27\64\1\0\37\64\1\0\72\64\2\0\13\64\2\0\10\64"+
+    "\1\0\65\64\1\0\104\64\11\0\44\64\3\0\2\64\4\0\36\64"+
+    "\70\0\131\64\22\0\7\64\16\0\2\65\56\0\106\65\32\0\2\65"+
+    "\44\0\1\64\1\65\3\64\1\0\1\64\1\0\24\64\1\0\54\64"+
+    "\1\0\7\64\3\0\1\64\1\0\1\64\1\0\1\64\1\0\1\64"+
+    "\1\0\22\64\15\0\14\64\1\0\102\64\1\0\14\64\1\0\44\64"+
+    "\1\0\4\65\11\0\65\64\2\0\2\64\2\0\2\64\3\0\34\64"+
+    "\2\0\10\64\2\0\2\64\67\0\46\64\2\0\1\64\7\0\46\64"+
+    "\12\0\21\65\1\0\27\65\1\0\3\65\1\0\1\65\1\0\2\65"+
+    "\1\0\1\65\13\0\33\64\5\0\3\64\56\0\32\64\5\0\1\65"+
+    "\12\64\10\65\15\0\12\65\6\0\1\65\107\64\2\0\5\64\1\0"+
+    "\17\64\1\0\4\64\1\0\1\64\17\65\2\64\2\65\1\0\4\65"+
+    "\2\0\12\65\u0207\0\3\65\1\0\65\64\2\0\1\65\1\64\20\65"+
+    "\3\0\4\65\3\0\12\64\2\65\2\0\12\65\21\0\3\65\1\0"+
+    "\10\64\2\0\2\64\2\0\26\64\1\0\7\64\1\0\1\64\3\0"+
+    "\4\64\2\0\1\65\1\0\7\65\2\0\2\65\2\0\3\65\11\0"+
+    "\1\65\4\0\2\64\1\0\3\64\2\65\2\0\12\65\2\64\20\0"+
+    "\1\65\2\0\6\64\4\0\2\64\2\0\26\64\1\0\7\64\1\0"+
+    "\2\64\1\0\2\64\1\0\2\64\2\0\1\65\1\0\5\65\4\0"+
+    "\2\65\2\0\3\65\13\0\4\64\1\0\1\64\7\0\12\65\2\65"+
+    "\3\64\14\0\3\65\1\0\7\64\1\0\1\64\1\0\3\64\1\0"+
+    "\26\64\1\0\7\64\1\0\2\64\1\0\5\64\2\0\1\65\1\64"+
+    "\10\65\1\0\3\65\1\0\3\65\22\0\1\64\5\0\12\65\21\0"+
+    "\3\65\1\0\10\64\2\0\2\64\2\0\26\64\1\0\7\64\1\0"+
+    "\2\64\2\0\4\64\2\0\1\65\1\64\6\65\3\0\2\65\2\0"+
+    "\3\65\10\0\2\65\4\0\2\64\1\0\3\64\4\0\12\65\22\0"+
+    "\2\65\1\0\6\64\3\0\3\64\1\0\4\64\3\0\2\64\1\0"+
+    "\1\64\1\0\2\64\3\0\2\64\3\0\3\64\3\0\10\64\1\0"+
+    "\3\64\4\0\5\65\3\0\3\65\1\0\4\65\11\0\1\65\17\0"+
+    "\11\65\21\0\3\65\1\0\10\64\1\0\3\64\1\0\27\64\1\0"+
+    "\12\64\1\0\5\64\4\0\7\65\1\0\3\65\1\0\4\65\7\0"+
+    "\2\65\11\0\2\64\4\0\12\65\22\0\2\65\1\0\10\64\1\0"+
+    "\3\64\1\0\27\64\1\0\12\64\1\0\5\64\4\0\7\65\1\0"+
+    "\3\65\1\0\4\65\7\0\2\65\7\0\1\64\1\0\2\64\4\0"+
+    "\12\65\22\0\2\65\1\0\10\64\1\0\3\64\1\0\27\64\1\0"+
+    "\20\64\4\0\6\65\2\0\3\65\1\0\4\65\11\0\1\65\10\0"+
+    "\2\64\4\0\12\65\221\0\56\64\1\0\1\64\1\65\2\64\7\65"+
+    "\5\0\6\64\1\65\10\65\1\0\12\65\47\0\2\64\1\0\1\64"+
+    "\2\0\2\64\1\0\1\64\2\0\1\64\6\0\4\64\1\0\7\64"+
+    "\1\0\3\64\1\0\1\64\1\0\1\64\2\0\2\64\1\0\2\64"+
+    "\1\0\1\64\1\65\2\64\6\65\1\0\2\65\1\64\2\0\5\64"+
+    "\1\0\1\65\1\0\6\65\2\0\12\65\76\0\2\65\6\0\12\65"+
+    "\13\0\1\65\1\0\1\65\1\0\1\65\4\0\2\65\10\64\1\0"+
+    "\41\64\7\0\24\65\1\0\6\65\4\0\6\65\1\0\1\65\1\0"+
+    "\25\65\3\0\7\65\1\0\1\65\346\0\46\64\12\0\47\64\11\0"+
+    "\1\64\1\0\2\64\1\0\3\64\1\0\1\64\1\0\2\64\1\0"+
+    "\5\64\51\0\1\64\1\0\1\64\1\0\1\64\13\0\1\64\1\0"+
+    "\1\64\1\0\1\64\3\0\2\64\3\0\1\64\5\0\3\64\1\0"+
+    "\1\64\1\0\1\64\1\0\1\64\1\0\1\64\3\0\2\64\3\0"+
+    "\2\64\1\0\1\64\50\0\1\64\11\0\1\64\2\0\1\64\2\0"+
+    "\2\64\7\0\2\64\1\0\1\64\1\0\7\64\50\0\1\64\4\0"+
+    "\1\64\10\0\1\64\u0c06\0\234\64\4\0\132\64\6\0\26\64\2\0"+
+    "\6\64\2\0\46\64\2\0\6\64\2\0\10\64\1\0\1\64\1\0"+
+    "\1\64\1\0\1\64\1\0\37\64\2\0\65\64\1\0\7\64\1\0"+
+    "\1\64\3\0\3\64\1\0\7\64\3\0\4\64\2\0\6\64\4\0"+
+    "\15\64\5\0\3\64\1\0\7\64\323\0\15\65\4\0\1\65\104\0"+
+    "\1\64\3\0\2\64\2\0\1\64\121\0\3\64\u0e82\0\1\65\1\0"+
+    "\1\64\31\0\11\64\6\65\1\0\5\65\13\0\124\64\4\0\2\65"+
+    "\2\0\2\65\2\0\132\64\1\0\3\65\6\0\50\64\u1cd3\0\u51a6\64"+
+    "\u0c5a\0\u2ba4\64\134\0\u0800\0\u1ffe\0\2\0";
+
+  /** 
+   * Translates characters to character classes
+   */
+  final private static char [] yycmap = yy_unpack_cmap(yycmap_packed);
+
+  /** 
+   * Translates a state to a row index in the transition table
+   */
+  final private static int yy_rowMap [] = { 
+        0,    55,   110,   165,   220,   275,   330,   385,   440,   495, 
+      550,   605,   660,   715,   770,   825,   880,   935,   990,  1045, 
+     1100,  1155,  1210,  1265,  1320,  1375,  1430,  1485,  1540,  1595, 
+     1650,  1705,  1760,  1815,  1870,  1925,  1980,  1925,  1980,  2035, 
+     1925,  1925,  1980,  2090,  2145,  2200,  2255,  2310,  2365,  2420, 
+     2475,  1925,  1980,  2530,  2585,  2640,  1925,  2695,  2695,  2750, 
+     2805,  2860,  2530,  1925,  2915,  2970,  1925,  3025,  3080,  3135, 
+     3190,  3245,  3300,  1925,  3355,  3410,  3465,  3520,  1925,  3575, 
+     3630,  3685,  3740,  3795,  1925,  3850,  3905,  3960,  4015,  4070, 
+     4125,  4180,  4235,  4235,  4290,  4345,  4400,  4455,  4455,  4510, 
+     4565,  4620,  4675,  4675,  4730,  4785,  4840,  4895,  1925,  4950, 
+     4950,  5005,  5060,  5115,  5170,  1925,  1925,  1980,  1925,  1925, 
+     5225,  5280,  5335,  5390,  5445,  5500,  5555,  5610,  1925,  5665, 
+     5720,  5775,  1925,  1925,  2695,  5830,  2805,  1925,  5885,  2860, 
+     2915,  3025,  3080,  5940,  3135,  1925,  5995,  3190,  1925,  3575, 
+     6050,  3685,  1925,  6105,  3740,  5225,  6160,  6215,  6270,  4015, 
+     1925,  6325,  6380,  4235,  6435,  4290,  1925,  6490,  6545,  6600, 
+     6600,  6655,  6710,  4400,  4235,  4455,  6765,  4510,  1925,  6820, 
+     4565,  4620,  4455,  4675,  6875,  4730,  1925,  6930,  6985,  7040, 
+     7040,  7095,  7150,  7205,  4950,  7260,  5005,  1925,  7315,  7370, 
+     7425,  7425,  7480,  7535,  7590,  7645,  7700,  7755,  7810,  1925, 
+     7865,  7920,  1925,  1925,  1925,  2255,  7975,  8030,  8085,  8140, 
+     8195,  8250,  8305,  6490,  8360,  8360,  6930,  8415,  8415,  8470, 
+     7315,  8525,  8525,  8580,  1925,  8635,  8690,  1925,  8745,  8800, 
+     8855,  8910,  8965,  9020,  9075,  9130,  6655,  7095,  9185,  7480, 
+     9240,  9295,  9350,  9405,  9460,  9515,  9570,  9625,  9680,  9735, 
+     9790,  9845,  9900,  9955, 10010, 10065, 10120,  1925,  1925, 10175, 
+    10230, 10285, 10340, 10395,  1925,  1925,  1925, 10450, 10505, 10560, 
+    10615, 10670, 10725,  1925, 10780,  4840,  5115, 10835, 10890, 10945, 
+    11000,  2255
+  };
+
+  /** 
+   * The packed transition table of the DFA
+   */
+  final private static String yy_packed = 
+    "\1\40\1\41\10\40\1\42\4\40\1\43\47\40\1\44"+
+    "\1\45\65\44\1\46\1\47\16\46\1\50\1\46\1\51"+
+    "\44\46\1\52\1\53\65\52\1\46\1\47\5\46\1\54"+
+    "\12\46\1\51\45\46\1\47\2\46\1\55\1\56\2\46"+
+    "\1\57\3\46\1\56\5\46\1\56\1\60\1\61\4\57"+
+    "\1\46\10\57\1\62\2\57\1\46\7\57\1\46\3\57"+
+    "\1\46\3\57\1\46\1\57\1\46\1\47\2\46\1\55"+
+    "\1\63\6\46\1\63\5\46\1\63\44\46\1\64\1\65"+
+    "\2\64\1\66\15\64\1\51\44\64\1\46\1\47\2\46"+
+    "\1\67\1\56\2\46\1\70\3\46\1\56\5\46\1\56"+
+    "\6\70\1\46\13\70\1\46\7\70\1\46\3\70\1\46"+
+    "\3\70\1\46\1\70\1\46\1\47\2\46\1\67\1\56"+
+    "\2\46\1\70\3\46\1\56\5\46\1\56\6\70\1\46"+
+    "\13\70\1\71\7\70\1\46\3\70\1\46\3\70\1\46"+
+    "\1\70\1\72\1\47\1\46\1\73\1\74\1\56\3\72"+
+    "\1\75\1\72\1\76\1\56\5\72\1\56\44\72\1\46"+
+    "\1\47\2\46\1\77\15\46\1\51\45\46\1\47\1\100"+
+    "\1\101\1\46\1\56\2\46\1\102\3\46\1\56\5\46"+
+    "\1\56\6\102\1\46\13\102\1\46\7\102\1\46\3\102"+
+    "\1\46\3\102\1\46\1\102\1\46\1\47\1\100\1\101"+
+    "\1\46\1\56\2\46\1\102\3\46\1\56\5\46\1\56"+
+    "\6\102\1\46\13\102\1\103\7\102\1\46\3\102\1\46"+
+    "\3\102\1\46\1\102\1\104\1\47\1\100\1\105\1\104"+
+    "\1\56\3\104\1\106\1\104\1\107\1\56\5\104\1\56"+
+    "\44\104\1\46\1\47\3\46\1\56\6\46\1\56\5\46"+
+    "\1\56\44\46\1\110\1\111\1\112\1\113\4\110\1\114"+
+    "\12\110\6\115\1\110\13\115\1\110\7\115\1\110\3\115"+
+    "\1\110\3\115\1\110\1\115\1\46\1\111\1\112\1\113"+
+    "\1\46\1\56\2\46\1\116\3\46\1\56\5\46\1\56"+
+    "\6\116\1\46\13\116\1\46\7\116\1\46\3\116\1\46"+
+    "\3\116\1\46\1\116\1\46\1\111\1\112\1\113\1\46"+
+    "\1\56\2\46\1\116\3\46\1\56\5\46\1\56\6\116"+
+    "\1\46\13\116\1\117\7\116\1\46\3\116\1\46\3\116"+
+    "\1\46\1\116\1\120\1\111\1\112\1\121\1\120\1\56"+
+    "\3\120\1\122\1\120\1\123\1\56\5\120\1\56\44\120"+
+    "\1\46\1\124\1\125\2\46\1\56\6\46\1\56\5\46"+
+    "\1\56\10\46\1\126\1\127\2\46\1\130\10\46\1\130"+
+    "\1\46\1\127\1\126\14\46\1\47\1\125\2\46\1\56"+
+    "\6\46\1\56\5\46\1\56\6\46\1\131\36\46\1\47"+
+    "\1\125\2\46\1\56\2\46\1\132\3\46\1\56\5\46"+
+    "\1\56\6\132\1\131\13\132\1\46\7\132\1\46\3\132"+
+    "\1\46\3\132\1\46\1\132\1\46\1\47\1\125\2\46"+
+    "\1\56\6\46\1\56\5\46\1\56\6\46\1\131\7\46"+
+    "\1\133\5\46\1\134\6\46\1\133\10\46\1\135\1\47"+
+    "\1\125\1\136\1\135\1\56\3\135\1\137\1\135\1\140"+
+    "\1\56\5\135\1\56\6\135\1\141\35\135\1\142\1\47"+
+    "\1\125\1\143\1\142\1\56\3\142\1\144\1\142\1\145"+
+    "\1\56\5\142\1\56\6\142\1\146\35\142\1\147\1\47"+
+    "\1\125\1\150\1\147\1\56\3\147\1\151\1\147\1\152"+
+    "\1\56\5\147\1\56\44\147\1\153\1\154\1\155\64\153"+
+    "\1\156\1\47\1\125\1\157\1\156\1\56\3\156\1\160"+
+    "\1\156\1\161\1\56\5\156\1\56\44\156\1\162\1\163"+
+    "\1\164\64\162\1\165\1\166\65\165\1\40\1\0\10\40"+
+    "\1\0\4\40\1\0\47\40\3\0\1\167\1\170\14\0"+
+    "\1\171\52\0\1\172\2\0\1\173\3\0\1\172\5\0"+
+    "\1\172\6\173\1\0\13\173\1\0\7\173\1\174\3\173"+
+    "\1\0\3\173\1\0\1\173\5\0\1\172\2\0\1\175"+
+    "\3\0\1\172\5\0\1\172\6\175\1\0\13\175\1\0"+
+    "\7\175\1\0\3\175\1\0\3\175\1\0\1\175\110\0"+
+    "\1\176\65\0\1\177\55\0\1\200\61\0\1\201\71\0"+
+    "\1\56\6\0\1\56\5\0\1\56\52\0\3\57\4\0"+
+    "\1\57\5\0\6\57\1\0\13\57\1\0\7\57\1\0"+
+    "\3\57\1\0\5\57\6\0\3\57\4\0\1\57\5\0"+
+    "\2\57\2\202\2\57\1\0\13\57\1\0\7\57\1\0"+
+    "\3\57\1\0\5\57\6\0\3\57\4\0\1\57\5\0"+
+    "\2\57\1\202\1\203\2\57\1\0\13\57\1\0\7\57"+
+    "\1\0\3\57\1\0\5\57\6\0\3\57\4\0\1\57"+
+    "\5\0\2\57\2\204\2\57\1\0\13\57\1\0\7\57"+
+    "\1\0\3\57\1\0\5\57\5\0\1\63\6\0\1\63"+
+    "\5\0\1\63\46\0\1\205\66\0\1\206\72\0\3\70"+
+    "\4\0\1\70\5\0\6\70\1\0\13\70\1\0\7\70"+
+    "\1\0\3\70\1\0\5\70\1\72\2\0\1\207\1\72"+
+    "\1\0\3\72\1\0\1\72\2\0\5\72\1\0\45\72"+
+    "\1\0\1\206\1\207\1\72\1\0\3\72\1\0\1\72"+
+    "\2\0\5\72\1\0\44\72\1\75\1\0\1\210\1\211"+
+    "\1\75\1\210\3\75\1\212\1\75\2\210\5\75\1\210"+
+    "\44\75\1\76\1\0\1\213\1\214\1\76\1\213\3\76"+
+    "\1\213\1\76\1\212\1\213\5\76\1\213\44\76\2\0"+
+    "\1\100\1\215\71\0\3\102\4\0\1\102\5\0\6\102"+
+    "\1\0\13\102\1\0\7\102\1\0\3\102\1\0\5\102"+
+    "\1\104\2\0\1\216\1\104\1\0\3\104\1\0\1\104"+
+    "\2\0\5\104\1\0\45\104\1\0\1\100\1\217\1\104"+
+    "\1\0\3\104\1\0\1\104\2\0\5\104\1\0\44\104"+
+    "\1\106\1\0\1\220\1\221\1\106\1\220\3\106\1\222"+
+    "\1\106\2\220\5\106\1\220\44\106\1\107\1\0\1\223"+
+    "\1\224\1\107\1\223\3\107\1\223\1\107\1\222\1\223"+
+    "\5\107\1\223\44\107\1\110\3\0\17\110\6\0\1\110"+
+    "\13\0\1\110\7\0\1\110\3\0\1\110\3\0\1\110"+
+    "\4\0\1\167\15\0\1\171\47\0\1\225\64\0\1\110"+
+    "\3\0\2\110\3\114\4\110\1\114\5\110\6\115\1\110"+
+    "\13\115\1\110\7\115\1\110\3\115\1\110\3\115\1\114"+
+    "\1\115\6\0\3\115\4\0\1\115\5\0\6\115\1\0"+
+    "\13\115\1\0\7\115\1\0\3\115\1\0\5\115\6\0"+
+    "\3\116\4\0\1\116\5\0\6\116\1\0\13\116\1\0"+
+    "\7\116\1\0\3\116\1\0\5\116\1\120\2\0\1\226"+
+    "\1\120\1\0\3\120\1\0\1\120\2\0\5\120\1\0"+
+    "\45\120\1\0\1\225\1\226\1\120\1\0\3\120\1\0"+
+    "\1\120\2\0\5\120\1\0\44\120\1\122\1\0\1\227"+
+    "\1\230\1\122\1\227\3\122\1\231\1\122\2\227\5\122"+
+    "\1\227\44\122\1\123\1\0\1\232\1\233\1\123\1\232"+
+    "\3\123\1\232\1\123\1\231\1\232\5\123\1\232\44\123"+
+    "\3\0\1\167\15\0\1\234\110\0\1\235\60\0\1\236"+
+    "\13\0\1\236\44\0\2\237\36\0\20\240\1\241\46\240"+
+    "\6\0\3\132\4\0\1\132\5\0\6\132\1\0\13\132"+
+    "\1\0\7\132\1\0\3\132\1\0\5\132\46\0\1\242"+
+    "\5\0\1\242\72\0\1\243\6\0\1\135\2\0\1\244"+
+    "\1\135\1\0\3\135\1\0\1\135\2\0\5\135\1\0"+
+    "\44\135\1\137\1\0\1\245\1\246\1\137\1\245\3\137"+
+    "\1\247\1\137\2\245\5\137\1\245\44\137\1\250\1\0"+
+    "\1\251\1\252\1\253\1\251\3\253\1\251\1\250\1\254"+
+    "\1\255\3\253\1\250\1\253\1\255\6\253\1\250\32\253"+
+    "\2\250\1\253\1\141\2\240\1\256\1\141\1\240\3\141"+
+    "\1\240\1\141\2\240\3\141\1\257\1\141\1\240\44\141"+
+    "\1\142\2\0\1\260\1\142\1\0\3\142\1\0\1\142"+
+    "\2\0\5\142\1\0\44\142\1\144\2\261\1\262\1\144"+
+    "\1\261\3\144\1\263\1\144\2\261\5\144\1\261\44\144"+
+    "\1\145\2\264\1\265\1\145\1\264\3\145\1\264\1\145"+
+    "\1\263\1\264\5\145\1\264\44\145\1\146\2\240\1\266"+
+    "\1\146\1\240\3\146\1\240\1\146\2\240\3\146\1\267"+
+    "\1\146\1\240\44\146\1\147\2\0\1\270\1\147\1\0"+
+    "\3\147\1\0\1\147\2\0\5\147\1\0\44\147\1\151"+
+    "\1\0\1\271\1\272\1\151\1\271\3\151\1\273\1\151"+
+    "\2\271\5\151\1\271\44\151\1\274\1\0\1\275\1\276"+
+    "\1\277\1\275\3\277\1\275\1\274\1\300\1\301\3\277"+
+    "\1\274\1\277\1\301\6\277\1\274\32\277\2\274\1\277"+
+    "\2\153\1\0\66\153\1\0\16\153\1\302\45\153\1\156"+
+    "\2\0\1\303\1\156\1\0\3\156\1\0\1\156\2\0"+
+    "\5\156\1\0\44\156\1\160\1\0\1\304\1\305\1\160"+
+    "\1\304\3\160\1\306\1\160\2\304\5\160\1\304\44\160"+
+    "\1\307\1\0\1\310\1\311\1\312\1\310\3\312\1\310"+
+    "\1\307\1\313\1\314\3\312\1\307\1\312\1\314\6\312"+
+    "\1\307\32\312\2\307\1\312\2\162\1\0\66\162\1\0"+
+    "\16\162\1\315\45\162\7\0\1\316\21\0\1\317\42\0"+
+    "\1\172\2\0\1\40\3\0\1\172\5\0\1\172\6\40"+
+    "\1\0\13\40\1\0\7\40\1\0\3\40\1\0\3\40"+
+    "\1\0\1\40\1\320\1\0\3\320\1\321\3\173\1\320"+
+    "\1\0\1\320\1\321\1\173\1\320\1\0\2\320\1\321"+
+    "\6\173\1\320\13\173\1\320\7\173\1\320\3\173\1\322"+
+    "\5\173\15\0\1\323\6\0\1\324\42\0\1\320\1\0"+
+    "\3\320\1\321\3\175\1\320\1\0\1\320\1\321\1\175"+
+    "\1\320\1\0\2\320\1\321\6\175\1\320\13\175\1\320"+
+    "\7\175\1\320\3\175\1\325\5\175\31\0\1\317\37\0"+
+    "\1\326\66\0\1\327\72\0\3\57\4\0\1\57\5\0"+
+    "\4\57\2\330\1\0\13\57\1\0\7\57\1\0\3\57"+
+    "\1\0\5\57\6\0\3\57\4\0\1\57\5\0\4\57"+
+    "\1\330\1\331\1\0\13\57\1\0\7\57\1\0\3\57"+
+    "\1\0\5\57\6\0\3\57\4\0\1\57\5\0\6\57"+
+    "\1\0\13\57\1\0\1\57\1\332\5\57\1\0\3\57"+
+    "\1\0\5\57\1\210\1\0\7\210\1\212\55\210\1\213"+
+    "\1\0\11\213\1\212\53\213\1\220\1\0\7\220\1\222"+
+    "\55\220\1\223\1\0\11\223\1\222\53\223\1\227\1\0"+
+    "\7\227\1\231\55\227\1\232\1\0\11\232\1\231\53\232"+
+    "\32\0\1\333\30\0\1\333\40\0\1\334\13\0\1\334"+
+    "\54\0\1\335\10\0\1\335\57\0\1\336\14\0\1\336"+
+    "\72\0\1\337\4\0\1\245\1\0\7\245\1\247\55\245"+
+    "\1\250\1\0\1\251\1\340\1\250\1\251\3\250\1\251"+
+    "\1\250\1\247\1\251\5\250\1\251\44\250\1\251\1\0"+
+    "\11\251\1\247\53\251\1\250\1\0\1\251\1\340\1\250"+
+    "\1\251\3\250\1\251\1\250\1\341\1\251\5\250\1\251"+
+    "\44\250\13\0\1\342\53\0\1\251\1\0\11\251\1\341"+
+    "\53\251\11\261\1\263\55\261\13\264\1\263\53\264\1\271"+
+    "\1\0\7\271\1\273\55\271\1\274\1\0\1\275\1\343"+
+    "\1\274\1\275\3\274\1\275\1\274\1\273\1\275\5\274"+
+    "\1\275\44\274\1\275\1\0\11\275\1\273\53\275\1\274"+
+    "\1\0\1\275\1\343\1\274\1\275\3\274\1\275\1\274"+
+    "\1\344\1\275\5\274\1\275\44\274\13\0\1\345\53\0"+
+    "\1\275\1\0\11\275\1\344\53\275\2\153\1\0\26\153"+
+    "\1\346\35\153\1\304\1\0\7\304\1\306\55\304\1\307"+
+    "\1\0\1\310\1\347\1\307\1\310\3\307\1\310\1\307"+
+    "\1\306\1\310\5\307\1\310\44\307\1\310\1\0\11\310"+
+    "\1\306\53\310\1\307\1\0\1\310\1\347\1\307\1\310"+
+    "\3\307\1\310\1\307\1\350\1\310\5\307\1\310\44\307"+
+    "\13\0\1\351\53\0\1\310\1\0\11\310\1\350\53\310"+
+    "\2\162\1\0\26\162\1\352\35\162\7\0\1\353\111\0"+
+    "\1\354\34\0\1\320\1\0\10\320\1\0\4\320\1\0"+
+    "\41\320\1\0\6\320\1\0\3\320\1\321\4\320\1\0"+
+    "\1\320\1\321\2\320\1\0\2\320\1\321\36\320\1\355"+
+    "\5\320\15\0\1\323\43\0\1\356\22\0\1\357\14\0"+
+    "\3\357\2\0\1\357\10\0\1\357\1\0\2\357\3\0"+
+    "\1\357\2\0\2\357\11\0\1\57\1\360\1\57\4\0"+
+    "\1\57\5\0\6\57\1\0\13\57\1\0\7\57\1\0"+
+    "\3\57\1\0\5\57\6\0\3\57\4\0\1\57\5\0"+
+    "\6\57\1\0\11\57\1\361\1\57\1\0\7\57\1\0"+
+    "\3\57\1\0\5\57\35\0\1\362\13\0\1\362\44\0"+
+    "\2\363\63\0\2\364\75\0\1\365\13\0\1\365\44\0"+
+    "\2\366\41\0\2\367\1\0\3\367\2\0\1\254\4\367"+
+    "\1\0\10\367\1\0\32\367\2\0\1\367\3\0\2\370"+
+    "\1\0\3\370\2\0\1\300\4\370\1\0\10\370\1\0"+
+    "\32\370\2\0\1\370\2\153\1\0\27\153\1\371\34\153"+
+    "\3\0\2\372\1\0\3\372\2\0\1\313\4\372\1\0"+
+    "\10\372\1\0\32\372\2\0\1\372\2\162\1\0\27\162"+
+    "\1\373\34\162\33\0\1\374\114\0\1\355\22\0\1\357"+
+    "\14\0\3\357\2\0\1\357\10\0\1\357\1\0\2\357"+
+    "\3\0\1\357\1\0\1\356\2\357\11\0\3\57\4\0"+
+    "\1\57\5\0\6\57\1\0\7\57\1\375\3\57\1\0"+
+    "\7\57\1\0\3\57\1\0\5\57\6\0\3\57\4\0"+
+    "\1\57\5\0\6\57\1\0\6\57\1\376\4\57\1\0"+
+    "\7\57\1\0\3\57\1\0\5\57\46\0\1\377\5\0"+
+    "\1\377\54\0\1\u0100\63\0\1\u0101\10\0\1\u0101\55\0"+
+    "\1\u0102\10\0\1\u0102\60\0\1\u0103\24\0\2\153\1\0"+
+    "\30\153\1\u0104\33\153\2\162\1\0\30\162\1\u0105\33\162"+
+    "\34\0\1\u0106\40\0\3\57\4\0\1\57\5\0\6\57"+
+    "\1\0\13\57\1\0\3\57\1\u0107\3\57\1\0\3\57"+
+    "\1\0\5\57\6\0\3\57\4\0\1\57\5\0\6\57"+
+    "\1\0\3\57\1\u0108\7\57\1\0\3\57\1\u0108\3\57"+
+    "\1\0\3\57\1\0\5\57\47\0\1\u0109\60\0\1\u010a"+
+    "\14\0\1\u010a\54\0\1\u010b\47\0\2\u010c\72\0\1\u010d"+
+    "\30\0\1\u010d\3\0\2\153\1\0\31\153\1\u010e\32\153"+
+    "\2\162\1\0\31\162\1\u010f\32\162\35\0\1\u0110\37\0"+
+    "\3\57\4\0\1\57\5\0\6\57\1\0\13\57\1\0"+
+    "\6\57\1\u0111\1\0\3\57\1\0\5\57\5\0\1\u0112"+
+    "\3\57\3\0\1\u0112\1\57\4\0\1\u0112\6\57\1\0"+
+    "\13\57\1\0\7\57\1\0\3\57\1\0\5\57\37\0"+
+    "\1\u0113\10\0\1\u0113\53\0\1\u0114\13\0\1\u0114\52\0"+
+    "\1\u0115\13\0\1\u0115\15\0\2\153\1\0\32\153\1\u0116"+
+    "\31\153\2\162\1\0\32\162\1\u0117\31\162\34\0\1\u0118"+
+    "\40\0\3\57\4\0\1\57\5\0\5\57\1\u0119\1\0"+
+    "\13\57\1\0\7\57\1\0\3\57\1\0\5\57\5\0"+
+    "\1\u0112\6\0\1\u0112\5\0\1\u0112\44\0\2\153\1\0"+
+    "\31\153\1\u011a\32\153\2\162\1\0\31\162\1\u011b\32\162"+
+    "\31\0\1\u011c\43\0\3\57\4\0\1\57\5\0\6\57"+
+    "\1\0\5\57\1\u011d\5\57\1\0\7\57\1\0\3\57"+
+    "\1\0\5\57\2\153\1\0\26\153\1\u011e\35\153\2\162"+
+    "\1\0\26\162\1\u011f\35\162\6\0\3\57\4\0\1\57"+
+    "\5\0\6\57\1\0\7\57\1\u0120\3\57\1\0\7\57"+
+    "\1\0\3\57\1\0\5\57\6\0\3\57\4\0\1\57"+
+    "\5\0\6\57\1\0\13\57\1\0\7\57\1\0\3\57"+
+    "\1\0\4\57\1\u0121\6\0\3\57\4\0\1\57\5\0"+
+    "\6\57\1\0\5\57\1\u0122\5\57\1\0\7\57\1\0"+
+    "\3\57\1\0\5\57\6\0\3\57\4\0\1\57\5\0"+
+    "\6\57\1\0\5\57\1\u0123\5\57\1\0\7\57\1\0"+
+    "\3\57\1\0\5\57\6\0\3\57\4\0\1\57\5\0"+
+    "\6\57\1\0\13\57\1\0\3\57\1\u0124\3\57\1\0"+
+    "\3\57\1\0\5\57";
+
+  /** 
+   * The transition table of the DFA
+   */
+  final private static int yytrans [] = yy_unpack(yy_packed);
+
+
+  /* error codes */
+  final private static int YY_UNKNOWN_ERROR = 0;
+  // final private static int YY_ILLEGAL_STATE = 1;
+  final private static int YY_NO_MATCH = 2;
+  final private static int YY_PUSHBACK_2BIG = 3;
+
+  /* error messages for the codes above */
+  final private static String YY_ERROR_MSG[] = {
+    "Unkown internal scanner error",		//$NON-NLS-1$
+    "Internal error: unknown state",		//$NON-NLS-1$
+    "Error: could not match input",		//$NON-NLS-1$
+    "Error: pushback value was too large"	//$NON-NLS-1$
+  };
+
+  /**
+   * YY_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+   */
+  private final static byte YY_ATTRIBUTE[] = {
+     1,  0,  0,  0,  0,  1,  0,  0,  1,  1,  1,  0,  1,  1,  1,  1, 
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1, 
+     1,  1,  1,  9,  1,  9,  1,  1,  9,  9,  1,  1,  1,  1,  1,  1, 
+     1,  1,  1,  9,  1,  1,  1,  1,  9,  1,  1,  1,  1,  1,  1,  9, 
+     1,  1,  9,  1,  1,  1,  1,  1,  1,  9,  1,  1,  1,  1,  9,  1, 
+     1,  1,  1,  1,  9,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1, 
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  9,  1,  1,  1, 
+     1,  1,  1,  9,  9,  1,  9,  9,  1,  0,  1,  0,  1,  0,  0,  0, 
+     9,  1,  1,  1,  9,  9,  0,  0,  0,  9,  0,  0,  0,  0,  0,  0, 
+     0,  9,  0,  0,  9,  0,  0,  0,  9,  0,  0,  0,  0,  0,  0,  0, 
+     9,  0,  0,  0,  0,  0,  9,  1,  0,  0,  1,  1,  0,  0,  1,  0, 
+     0,  0,  9,  0,  0,  0,  1,  0,  0,  0,  9,  1,  0,  0,  1,  1, 
+     0,  1,  0,  0,  0,  9,  1,  0,  0,  1,  1,  0,  1,  0,  0,  1, 
+     1,  9,  0,  0,  9,  9,  9,  1,  1,  1,  0,  0,  0,  0,  0,  0, 
+     1,  0,  0,  1,  0,  1,  0,  1,  0,  1,  9,  0,  1,  9,  0,  1, 
+     1,  0,  0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  1,  0,  0, 
+     0,  0,  0,  1,  1,  0,  1,  1,  0,  0,  0,  9,  9,  1,  1,  0, 
+     1,  1,  9,  9,  9,  1,  1,  0,  1,  1,  1,  9,  1,  1,  1,  1, 
+     1,  1,  1,  1
+  };
+
+  /** the input device */
+  private java.io.Reader yy_reader;
+
+  /** the current state of the DFA */
+  private int yy_state;
+
+  /** the current lexical state */
+  private int yy_lexical_state = YYINITIAL;
+
+  /** this buffer contains the current text to be matched and is
+      the source of the yytext() string */
+  private char yy_buffer[] = new char[16384];
+
+  /** the textposition at the last accepting state */
+  private int yy_markedPos;
+
+  /** the textposition at the last state to be included in yytext */
+  private int yy_pushbackPos;
+
+  /** the current text position in the buffer */
+  private int yy_currentPos;
+
+  /** startRead marks the beginning of the yytext() string in the buffer */
+  private int yy_startRead;
+
+  /** endRead marks the last character in the buffer, that has been read
+      from input */
+  private int yy_endRead;
+
+  /** number of newlines encountered up to the start of the matched text */
+  private int yyline;
+
+  /** the number of characters up to the start of the matched text */
+  private int yychar;
+
+  /**
+   * the number of characters from the last newline up to the start of the 
+   * matched text
+   */
+  // private int yycolumn; 
+
+  /** 
+   * yy_atBOL == true <=> the scanner is currently at the beginning of a line
+   */
+  // private boolean yy_atBOL;
+
+  /** yy_atEOF == true <=> the scanner has returned a value for EOF */
+  private boolean yy_atEOF;
+
+  /** denotes if the user-EOF-code has already been executed */
+  private boolean yy_eof_done;
+
+  /* user code: */
+	private int fTokenCount = 0;
+ 
+	// required holders for white-space compacting
+	private boolean fShouldLoadBuffered = false;
+	private String fBufferedContext = null;
+	private int fBufferedStart = 1;
+	private int fBufferedLength = 0;
+	private String f_context = null;
+
+	// state stack for handling embedded regions
+	private IntStack fStateStack = new IntStack();
+
+	private String context = null;
+	private int start = 0;
+	private int textLength = 0;
+	private int length = 0;
+
+	// offset for tracking position specific block tags
+	private int fOffset = 0;
+	
+	// the name of the current tag being opened
+	private String fCurrentTagName = null;
+
+	// the list of tag name BlockMarkers
+	private List fBlockMarkers = new ArrayList();
+
+	// required to not seek text blocks on an end tag
+	private boolean fIsBlockingEnabled = false;
+	private boolean fIsCaseSensitiveBlocking = true;
+
+	private XMLParserRegionFactory fRegionFactory = new XMLParserRegionFactory();
+/**
+ * user method 
+ */
+public final void addBlockMarker(BlockMarker marker) {
+	if(containsTagName(marker.getTagName()))
+		return;
+	fBlockMarkers.add(marker);
+}
+/**
+ * user method 
+ */
+public final void removeBlockMarker(BlockMarker marker) {
+	fBlockMarkers.remove(marker);
+}
+/**
+ * user method 
+ */
+public final void removeBlockMarker(String tagname) {
+	if (fBlockMarkers != null) {
+		Iterator blocks = fBlockMarkers.iterator();
+		while (blocks.hasNext()) {
+			if (((BlockMarker) blocks.next()).getTagName().equals(tagname))
+				blocks.remove();
+		}
+	}
+}
+/* user method */
+public final boolean isCaseSensitiveBlocking() {
+	return fIsCaseSensitiveBlocking;
+}
+/* user method */
+public final void setCaseSensitiveBlocking(boolean newValue) {
+	fIsCaseSensitiveBlocking = newValue;
+}
+/* user method */
+public boolean getBlockMarkerCaseSensitivity() {
+        return getBlockMarkerCaseSensitivity(fCurrentTagName);
+}
+/* user method */
+public boolean getBlockMarkerCaseSensitivity(String name) {
+	Iterator iterator = fBlockMarkers.iterator();
+	while(iterator.hasNext()) {
+		BlockMarker marker = (BlockMarker)iterator.next();
+		boolean casesensitive = marker.isCaseSensitive();
+		if(casesensitive && marker.getTagName().equals(name))
+			return casesensitive;
+		else if(!casesensitive && marker.getTagName().equalsIgnoreCase(name))
+			return casesensitive;
+	}
+	return true;
+}
+/* user method */
+public String getBlockMarkerContext() {
+	return getBlockMarkerContext(fCurrentTagName);
+}
+/* user method */
+public String getBlockMarkerContext(String name) {
+	Iterator iterator = fBlockMarkers.iterator();
+	while(iterator.hasNext()) {
+		BlockMarker marker = (BlockMarker)iterator.next();
+		if(marker.getTagName().equals(name))
+			return marker.getContext();
+	}
+	return BLOCK_TEXT;
+}
+/* user method */
+public List getBlockMarkers() {
+	return fBlockMarkers;
+}
+/* user method */
+public final int getOffset() {
+	return fOffset + yychar;
+}
+private final boolean isBlockMarker() {
+	return isBlockMarker(fCurrentTagName);
+}
+private final boolean isBlockMarker(String tagName) {
+	if (!fIsBlockingEnabled)
+		return false;
+	return containsTagName(tagName);
+}
+/**
+ * user method
+ */
+public final void beginBlockTagScan(String newTagName) {
+	beginBlockMarkerScan(newTagName, BLOCK_TEXT);
+}
+/**
+ * user method
+ *
+ * Special tokenizer setup.  Allows tokenization to be initiated at the
+ * start of a text block within a "newTagName" tag.
+ *
+ * Example: 
+ *	Tokenizer toker = new Tokenizer();
+ *	toker.setCaseSensitiveBlocking(false);
+ *	toker.reset(new java.io.StringReader("afiuhqwkejhtasihgalkwhtq</scripter></scr></script>asgdasga"));
+ *	toker.beginBlockMarkerScan("script", BLOCK_TEXT);
+ *	toker.getRegions(); 
+ *
+ * Returns:
+ *	BLOCK_TEXT: 0-40
+ *	XML_END_TAG_OPEN: 41-42
+ *	XML_TAG_NAME: 43-48
+ *	XML_TAG_CLOSE: 49-49
+ *	XML_CONTENT: 50-57
+ *
+ */
+public final void beginBlockMarkerScan(String newTagName, String blockcontext) {
+	yybegin(ST_BLOCK_TAG_SCAN);
+	fCurrentTagName = newTagName;
+}
+/**
+ * Method doScan.
+ * 
+ * Returns a context region for all of the text from the current position upto the end of input or
+ * to right *before* the first occurence of searchString
+ * 
+ * @param searchString - target string to search for ex.: "-->", "</tagname"
+ * @param requireTailSeparator - whether the target must be immediately followed by whitespace or '>'
+ * @param context - the context of the scanned region if non-zero length
+ * @param exitState - the state to go to if the region was of non-zero length
+ * @param abortState - the state to go to if the searchString was found immediately
+ * @return String - the context found: the desired context on a non-zero length match, the abortContext on immediate success
+ * @throws IOException
+ */
+private final String doScan(String searchString, boolean requireTailSeparator, String searchContext, int exitState, int immediateFallbackState) throws IOException {
+	boolean stillSearching = true;
+	// Disable further block (probably)
+	fIsBlockingEnabled = false;
+	int searchStringLength = searchString.length();
+	int n = 0;
+	char lastCheckChar;
+	int i;
+	boolean same = false;
+	while (stillSearching) {
+		n = 0;
+		// Ensure that enough data from the input exists to compare against the search String.
+		n = yy_advance();
+		while(n != YYEOF && yy_currentPos < searchStringLength)
+			n = yy_advance();
+		// If the input was too short or we've exhausted the input, stop immediately.
+		if (n == YYEOF) {
+			stillSearching = false;
+		}
+		else {
+			same = true;
+			// Ensure that we've not encountered a complete block (<%%>) that was *shorter* than the closeTagString and
+			// thus found twice at current-targetLength [since the first scan would have come out this far anyway].
+			// Check the characters in the target versus the last targetLength characters read from the buffer
+			// and see if it matches
+			
+			// safety check for array accesses (yy_currentPos is the *last* character we can check against)
+			if(yy_currentPos >= searchStringLength && yy_currentPos <= yy_buffer.length) {
+				for(i = 0; i < searchStringLength; i++) {
+					if(same && fIsCaseSensitiveBlocking)
+						same = yy_buffer[i + yy_currentPos - searchStringLength] == searchString.charAt(i);
+					else if(same && !fIsCaseSensitiveBlocking)
+						same = Character.toLowerCase(yy_buffer[i + yy_currentPos - searchStringLength]) == Character.toLowerCase(searchString.charAt(i));
+				}
+			}
+			// safety check failed; no match is possible right now
+			else {
+				same = false;
+			}
+			if (same && requireTailSeparator && yy_currentPos < yy_buffer.length) {
+				// Additional check for close tags to ensure that targetString="</script" doesn't match
+				// "</scriptS"
+				lastCheckChar = yy_buffer[yy_currentPos];
+				// Succeed on "</script>" and "</script "
+				if(lastCheckChar == '>' || Character.isWhitespace(lastCheckChar))
+					stillSearching = false;
+			}
+			else {
+				stillSearching = !same || (yy_currentPos < yy_startRead + searchStringLength);
+			}
+		}
+	}
+	if (n != YYEOF || same) {
+		// We've stopped short of the end or definitely found a match
+		yy_markedPos = yy_currentPos - searchStringLength;
+		yy_currentPos = yy_markedPos + 1;
+		// If the searchString occurs at the very beginning of what would have
+		// been a Block, resume scanning normally immediately
+		if (yy_markedPos == yy_startRead) {
+			yybegin(immediateFallbackState);
+			return primGetNextToken();
+		}
+	}
+	else {
+		// We ran through the rest of the input
+		yy_markedPos = yy_currentPos;
+		yy_currentPos++;
+	}
+	yybegin(exitState);
+	// If the ending occurs at the very beginning of what would have
+	// been a Block, resume scanning normally immediately
+	if(yy_markedPos == yy_startRead)
+		return primGetNextToken();
+	return searchContext;
+}
+/**
+ * user method
+ *
+ * A generic lookahead-like operation
+ */
+private final String doBlockScan(String target, String targetContext, int immediateFallbackState) throws IOException {
+	return doScan(target, false, targetContext, immediateFallbackState, immediateFallbackState);
+}
+/**
+ * user method 
+ * does a lookahead for the current tag name
+ */
+private final String doBlockTagScan() throws IOException {
+        fIsCaseSensitiveBlocking = getBlockMarkerCaseSensitivity();
+	return doScan("</" + fCurrentTagName, true, getBlockMarkerContext(fCurrentTagName), YYINITIAL, YYINITIAL);
+}
+/**
+ * user method
+ *
+ * Converts the raw context String returned by the primGetNextToken()
+ * method into a full ITextRegion by pulling in values for the
+ * current offset within the scanning text.
+ *
+ * Returns null when EOF is encountered and attaches intermittently
+ * discovered whitespace onto the end of useful regions.
+ *
+ * Note that this algorithm caches the token following the one being returned
+ * so that whitespace can be collapsed.
+ */
+public final ITextRegion getNextToken() throws IOException {
+	// load the starting non-whitespace token (assume that it is so)
+	if (fShouldLoadBuffered) {
+		context = fBufferedContext;
+		start = fBufferedStart;
+		textLength = length = fBufferedLength;
+		fShouldLoadBuffered = false;
+	}
+	else {
+		context = primGetNextToken();
+		if (context == XML_TAG_NAME) {
+			if(containsTagName(yy_buffer, yy_startRead, yy_markedPos-yy_startRead))
+				fCurrentTagName = yytext();
+			else
+				fCurrentTagName = null;
+		}
+		else if (context == XML_TAG_OPEN) {
+			fIsBlockingEnabled = true;
+		}
+		else if (context == XML_END_TAG_OPEN) {
+			fIsBlockingEnabled = false;
+		}
+		start = yychar;
+		textLength = length = yylength();
+		if (yy_atEOF) {
+			fTokenCount++;
+			return null;
+		}
+	}
+	// store the next token
+	f_context = primGetNextToken();
+	if (f_context == XML_TAG_NAME) {
+		if(containsTagName(yy_buffer, yy_startRead, yy_markedPos-yy_startRead))
+			fCurrentTagName = yytext();
+		else
+			fCurrentTagName = null;
+	}
+	else if (f_context == XML_TAG_OPEN) {
+		fIsBlockingEnabled = true;
+	}
+	else if (f_context == XML_END_TAG_OPEN) {
+		fIsBlockingEnabled = false;
+	}
+	fBufferedContext = f_context;
+	fBufferedStart = yychar;
+	fBufferedLength = yylength();
+	fShouldLoadBuffered = true;
+	if (fBufferedContext == WHITE_SPACE) {
+		fShouldLoadBuffered = false;
+		length += fBufferedLength;
+	}
+	if (context == null) {
+		// EOF
+		if (Debug.debugTokenizer) {
+			System.out.println(getClass().getName() + " discovered " + fTokenCount + " tokens."); //$NON-NLS-2$//$NON-NLS-1$
+		}
+		return null;
+	}
+	fTokenCount++;
+	return fRegionFactory.createToken(context, start, textLength, length, null, fCurrentTagName);
+}
+/* user method */
+public XMLTokenizer(){
+	super();
+}
+/* user method */
+public XMLTokenizer(char[] charArray){
+		this(new CharArrayReader(charArray));
+}
+/* user method */
+public void reset(char[] charArray) {
+	reset(new CharArrayReader(charArray), 0);
+}
+/* user method */
+public void reset(char[] charArray, int newOffset) {
+	reset(new CharArrayReader(charArray), newOffset);
+}
+/* user method */
+public void reset(java.io.InputStream in) {
+	reset(new java.io.InputStreamReader(in), 0);
+}
+/* user method */
+public void reset(java.io.InputStream in, int newOffset) {
+	reset(new java.io.InputStreamReader(in), newOffset);
+}
+/* user method */
+public void reset(java.io.Reader in) {
+	reset(in, 0);
+}
+/**
+ * user method *
+ *
+ * Reset internal counters and vars to "newly created" values, in the hopes
+ * that resetting a pre-existing tokenizer is faster than creating a new one.
+ *
+ * This method contains code blocks that were essentially duplicated from the
+ * <em>generated</em> output of this specification before this method was
+ * added.  Those code blocks were under the above copyright.
+ */
+public void reset(java.io.Reader in, int newOffset) {
+	if (Debug.debugTokenizer) {
+		System.out.println("resetting tokenizer");//$NON-NLS-1$
+	}
+	fOffset = newOffset;
+
+	/* the input device */
+	yy_reader = in;
+
+	/* the current state of the DFA */
+	yy_state = 0;
+
+	/* the current lexical state */
+	yy_lexical_state = YYINITIAL;
+
+	/* this buffer contains the current text to be matched and is
+	the source of the yytext() string */
+	java.util.Arrays.fill(yy_buffer, (char)0);
+
+	/* the textposition at the last accepting state */
+	yy_markedPos = 0;
+
+	/* the textposition at the last state to be included in yytext */
+	yy_pushbackPos = 0;
+
+	/* the current text position in the buffer */
+	yy_currentPos = 0;
+
+	/* startRead marks the beginning of the yytext() string in the buffer */
+	yy_startRead = 0;
+
+	/** 
+	 * endRead marks the last character in the buffer, that has been read
+	 * from input 
+	 */
+	yy_endRead = 0;
+
+	/* number of newlines encountered up to the start of the matched text */
+	yyline = 0;
+
+	/* the number of characters up to the start of the matched text */
+	yychar = 0;
+
+	/* yy_atEOF == true <=> the scanner has returned a value for EOF */
+	yy_atEOF = false;
+
+	/* denotes if the user-EOF-code has already been executed */
+	yy_eof_done = false;
+
+
+	/* user vars: */
+	fTokenCount = 0;
+ 
+	fShouldLoadBuffered = false;
+	fBufferedContext = null;
+	fBufferedStart = 1;
+	fBufferedLength = 0;
+	fStateStack = new IntStack();
+
+	context = null;
+	start = 0;
+	textLength = 0;
+	length = 0;
+}
+
+	/**
+	 * user method
+	 *
+	 */
+	public BlockTokenizer newInstance() {
+		XMLTokenizer newInstance = new XMLTokenizer();
+		// global tagmarkers can be shared; they have no state and 
+		// are never destroyed (e.g. 'release')
+		for(int i = 0; i < fBlockMarkers.size(); i++) {
+			BlockMarker blockMarker = (BlockMarker) fBlockMarkers.get(i);
+			if(blockMarker.isGlobal())
+				newInstance.addBlockMarker(blockMarker);
+		}
+		return newInstance;
+	}
+/* user method */
+private final String scanXMLCommentText() throws IOException {
+	// Scan for '-->' and return the text up to that point as
+	//   XML_COMMENT_TEXT unless the string occurs IMMEDIATELY, in which
+	//  case change to the ST_XML_COMMENT_END state and return the next
+	//  context as usual.
+	return doScan("-->", false, XML_COMMENT_TEXT, ST_XML_COMMENT_END, ST_XML_COMMENT_END);
+}
+
+
+  /**
+   * Creates a new scanner
+   * There is also a java.io.InputStream version of this constructor.
+   *
+   * @param   in  the java.io.Reader to read input from.
+   */
+  public XMLTokenizer(java.io.Reader in) {
+    this.yy_reader = in;
+  }
+
+  /**
+   * Creates a new scanner.
+   * There is also java.io.Reader version of this constructor.
+   *
+   * @param   in  the java.io.Inputstream to read input from.
+   */
+  public XMLTokenizer(java.io.InputStream in) {
+    this(new java.io.InputStreamReader(in));
+  }
+
+  /** 
+   * Unpacks the compressed DFA transition table.
+   *
+   * @param packed   the packed transition table
+   * @return         the unpacked transition table
+   */
+  private static int [] yy_unpack(String packed) {
+    int [] trans = new int[11055];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 3734) {
+      int count = packed.charAt(i++);
+      int value = packed.charAt(i++);
+      value--;
+      do trans[j++] = value; while (--count > 0);
+    }
+    return trans;
+  }
+
+  /** 
+   * Unpacks the compressed character translation table.
+   *
+   * @param packed   the packed character translation table
+   * @return         the unpacked character translation table
+   */
+  private static char [] yy_unpack_cmap(String packed) {
+    char [] map = new char[0x10000];
+    int i = 0;  /* index in packed string  */
+    int j = 0;  /* index in unpacked array */
+    while (i < 1372) {
+      int  count = packed.charAt(i++);
+      char value = packed.charAt(i++);
+      do map[j++] = value; while (--count > 0);
+    }
+    return map;
+  }
+
+
+  /**
+   * Gets the next input character.
+   *
+   * @return      the next character of the input stream, EOF if the
+   *              end of the stream is reached.
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  private int yy_advance() throws java.io.IOException {
+
+    /* standard case */
+    if (yy_currentPos < yy_endRead) return yy_buffer[yy_currentPos++];
+
+    /* if the eof is reached, we don't need to work hard */ 
+    if (yy_atEOF) return YYEOF;
+
+    /* otherwise: need to refill the buffer */
+
+    /* first: make room (if you can) */
+    if (yy_startRead > 0) {
+      System.arraycopy(yy_buffer, yy_startRead, 
+                       yy_buffer, 0, 
+                       yy_endRead-yy_startRead);
+
+      /* translate stored positions */
+      yy_endRead-= yy_startRead;
+      yy_currentPos-= yy_startRead;
+      yy_markedPos-= yy_startRead;
+      yy_pushbackPos-= yy_startRead;
+      yy_startRead = 0;
+    }
+
+    /* is the buffer big enough? */
+    if (yy_currentPos >= yy_buffer.length) {
+      /* if not: blow it up */
+      char newBuffer[] = new char[yy_currentPos*2];
+      System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);
+      yy_buffer = newBuffer;
+    }
+
+    /* finally: fill the buffer with new input */
+    int numRead = yy_reader.read(yy_buffer, yy_endRead, 
+                                            yy_buffer.length-yy_endRead);
+
+    if ( numRead == -1 ) return YYEOF;
+
+    yy_endRead+= numRead;
+
+    return yy_buffer[yy_currentPos++];
+  }
+
+    
+  /**
+   * Closes the input stream.
+   */
+  final public void yyclose() throws java.io.IOException {
+    yy_atEOF = true;            /* indicate end of file */
+    yy_endRead = yy_startRead;  /* invalidate buffer    */
+    yy_reader.close();
+  }
+
+
+  /**
+   * Returns the current lexical state.
+   */
+  final public int yystate() {
+    return yy_lexical_state;
+  }
+
+  /**
+   * Enters a new lexical state
+   *
+   * @param newState the new lexical state
+   */
+  final public void yybegin(int newState) {
+    yy_lexical_state = newState;
+  }
+
+
+  /**
+   * Returns the text matched by the current regular expression.
+   */
+  final public String yytext() {
+    return new String( yy_buffer, yy_startRead, yy_markedPos-yy_startRead );
+  }
+
+  /**
+   * Returns the length of the matched text region.
+   */
+  final public int yylength() {
+    return yy_markedPos-yy_startRead;
+  }
+
+
+  /**
+   * Reports an error that occured while scanning - from the SED JFlex skeleton
+   *
+   * @param   errorCode  the code of the errormessage to display
+   */
+  private void yy_ScanError(int errorCode) {
+    try {
+      Logger.log(Logger.ERROR, YY_ERROR_MSG[errorCode]);
+    }
+    catch (ArrayIndexOutOfBoundsException e) {
+      Logger.log(Logger.ERROR, YY_ERROR_MSG[YY_UNKNOWN_ERROR]);
+    }
+    // DO NOT EXIT the VM on an error
+    // System.exit(1);
+  } 
+
+
+  /**
+   * Pushes the specified amount of characters back into the input stream.
+   *
+   * They will be read again by then next call of the scanning method
+   *
+   * @param number  the number of characters to be read again.
+   *                This number must not be greater than yylength()!
+   */
+  void yypushback(int number) {
+    if ( number > yylength() )
+      yy_ScanError(YY_PUSHBACK_2BIG);
+
+    yy_markedPos -= number;
+  }
+
+	/**
+	 * user method - skeleton.sed
+	 */
+	protected final boolean containsTagName(char[] markerTagName, int offset, int tagnameLength) {
+		for(int j = 0; j < fBlockMarkers.size(); j++) {
+			BlockMarker marker = (BlockMarker)fBlockMarkers.get(j);
+			if(marker.getTagName().length() == tagnameLength) {
+				boolean matchesSoFar = true;
+				for(int i = 0; i < tagnameLength && matchesSoFar; i++) {
+					if(marker.isCaseSensitive()) {
+						if(marker.getTagName().charAt(i) != markerTagName[i + offset])
+							matchesSoFar = false;
+					}
+					else {
+						if(Character.toLowerCase(marker.getTagName().charAt(i)) != Character.toLowerCase(markerTagName[i + offset]))
+							matchesSoFar = false;
+					}
+				}
+				if(matchesSoFar)
+					return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * user method - skeleton.sed
+	 *
+	 * Return ALL of the regions scannable within the remaining text
+	 * Note: for verification use
+	 */
+	public final List getRegions() {
+		List tokens = new ArrayList();
+		ITextRegion region = null;
+		try {
+			region = getNextToken();
+			while(region != null) {
+				if (region != null) {
+					tokens.add(region);
+				}
+				region = getNextToken();
+			}
+		}
+		catch (StackOverflowError e) {
+			Logger.logException(getClass().getName()+": input could not be tokenized correctly at position " + getOffset(), e);//$NON-NLS-1$
+			throw e;
+		}
+		catch (Exception e) {
+			// Since this is convenience method and NOT the recommended 
+			// way of getting tokens, many errors are simply hidden
+			Logger.logException("Exception not handled retrieving regions: " + e.getLocalizedMessage(), e);//$NON-NLS-1$
+		}
+		return tokens;
+	}
+	/**
+	 * user method - skeleton.sed
+	 */
+	private final void dump(String s) {
+		if (Debug.debugTokenizer) {
+			System.out.println(s + " (" + yychar + "-" + //$NON-NLS-2$//$NON-NLS-1$
+				(yylength() + yychar) + "):\'" +//$NON-NLS-1$
+					StringUtils.escape(yytext()) + "\'");//$NON-NLS-1$
+		}
+	}
+	/* user method  - skeleton.sed */
+	public final boolean isEOF() {
+		return yy_atEOF;
+	}
+/* user method - skeleton.sed */
+protected final boolean containsTagName(String markerTagName) {
+	Iterator blocks = fBlockMarkers.iterator();
+	while(blocks.hasNext()) {
+		BlockMarker marker = (BlockMarker)blocks.next();
+		if(marker.isCaseSensitive()) {
+			if(marker.getTagName().equals(markerTagName))
+				return true;
+		}
+		else {
+			if(marker.getTagName().equalsIgnoreCase(markerTagName))
+				return true;
+		}
+	}
+	return false;
+}
+
+  /**
+   * Contains user EOF-code, which will be executed exactly once,
+   * when the end of file is reached
+   */
+  private void yy_do_eof() {
+    if (!yy_eof_done) {
+      yy_eof_done = true;
+    // do nothing, this is the downstream parser's job
+
+    }
+  }
+
+
+  /**
+   * Resumes scanning until the next regular expression is matched,
+   * the end of input is encountered or an I/O-Error occurs.
+   *
+   * @return      the next token
+   * @exception   IOException  if any I/O-Error occurs
+   */
+  public String primGetNextToken() throws java.io.IOException {
+    int yy_input;
+    int yy_action;
+
+
+    while (true) {
+
+      yychar+= yylength();
+
+      boolean yy_counted = false;
+      for (yy_currentPos = yy_startRead; yy_currentPos < yy_markedPos;
+                                                      yy_currentPos++) {
+        switch (yy_buffer[yy_currentPos]) {
+        case '\r':
+          yyline++;
+          yy_counted = true;
+          break;
+        case '\n':
+          if (yy_counted)
+            yy_counted = false;
+          else {
+            yyline++;
+          }
+          break;
+        default:
+          yy_counted = false;
+        }
+      }
+
+      if (yy_counted) {
+        if ( yy_advance() == '\n' ) yyline--;
+        if ( !yy_atEOF ) yy_currentPos--;
+      }
+
+      yy_action = -1;
+
+      yy_currentPos = yy_startRead = yy_markedPos;
+
+      yy_state = yy_lexical_state;
+
+
+      yy_forAction: {
+        while (true) {
+    
+          yy_input = yy_advance();
+
+          if ( yy_input == YYEOF ) break yy_forAction;
+
+          int yy_next = yytrans[ yy_rowMap[yy_state] + yycmap[yy_input] ];
+          if (yy_next == -1) break yy_forAction;
+          yy_state = yy_next;
+
+          int yy_attributes = YY_ATTRIBUTE[yy_state];
+          if ( (yy_attributes & 1) > 0 ) {
+            yy_action = yy_state; 
+            yy_markedPos = yy_currentPos; 
+            if ( (yy_attributes & 8) > 0 ) break yy_forAction;
+          }
+
+        }
+      }
+
+
+      switch (yy_action) {    
+
+        case 291: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XSL processing instruction target");//$NON-NLS-1$
+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 293: break;
+        case 283: 
+        case 285: 
+        case 286: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nCDATA start");//$NON-NLS-1$
+	fStateStack.push(yystate());
+	yybegin(ST_CDATA_TEXT);
+	return XML_CDATA_OPEN;
+ }
+        case 294: break;
+        case 276: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("element");//$NON-NLS-1$
+	yybegin(ST_XML_ELEMENT_DECLARATION);
+	return XML_ELEMENT_DECLARATION;
+ }
+        case 295: break;
+        case 275: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist");//$NON-NLS-1$
+	yybegin(ST_XML_ATTLIST_DECLARATION);
+	return XML_ATTLIST_DECLARATION;
+ }
+        case 296: break;
+        case 274: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_DECLARATION);
+	return XML_DOCTYPE_DECLARATION;
+ }
+        case 297: break;
+        case 268: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype external id");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_ID_PUBLIC);
+	return XML_DOCTYPE_EXTERNAL_ID_PUBLIC;
+ }
+        case 298: break;
+        case 267: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype external id");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_ID_SYSTEM);
+	return XML_DOCTYPE_EXTERNAL_ID_SYSTEM;
+ }
+        case 299: break;
+        case 263: 
+        case 273: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction target");//$NON-NLS-1$
+        yybegin(ST_DHTML_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 300: break;
+        case 237: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nCharRef");//$NON-NLS-1$
+	return XML_CHAR_REFERENCE;
+ }
+        case 301: break;
+        case 234: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\ncomment start");//$NON-NLS-1$
+	yybegin(ST_XML_COMMENT);
+	return XML_COMMENT_OPEN;
+ }
+        case 302: break;
+        case 215: 
+        case 216: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction target");//$NON-NLS-1$
+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 303: break;
+        case 214: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("comment end");//$NON-NLS-1$
+	yybegin(YYINITIAL);
+	return XML_COMMENT_CLOSE;
+ }
+        case 304: break;
+        case 213: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("CDATA end");//$NON-NLS-1$
+	yybegin(fStateStack.pop());
+	return XML_CDATA_CLOSE;
+ }
+        case 305: break;
+        case 212: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nPEReference");//$NON-NLS-1$
+	return XML_PE_REFERENCE;
+ }
+        case 306: break;
+        case 209: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nEntityRef");//$NON-NLS-1$
+	return XML_ENTITY_REFERENCE;
+ }
+        case 307: break;
+        case 160: 
+        case 174: 
+        case 182: 
+          { 
+	return XML_DOCTYPE_INTERNAL_SUBSET;
+ }
+        case 308: break;
+        case 148: 
+          { 
+        yybegin(YYINITIAL);
+	if(Debug.debugTokenizer)
+		dump("empty tag close");//$NON-NLS-1$
+        return XML_EMPTY_TAG_CLOSE;
+ }
+        case 309: break;
+        case 133: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction end");//$NON-NLS-1$
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 310: break;
+        case 132: 
+          { 
+		// ended with nothing inside
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 311: break;
+        case 128: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("processing instruction end");//$NON-NLS-1$
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 312: break;
+        case 120: 
+          { 
+	fStateStack.push(yystate());
+	if(Debug.debugTokenizer)
+		dump("\ndeclaration start");//$NON-NLS-1$
+        yybegin(ST_XML_DECLARATION);
+	return XML_DECLARATION_OPEN;
+ }
+        case 313: break;
+        case 119: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nprocessing instruction start");//$NON-NLS-1$
+	yybegin(ST_PI);
+        return XML_PI_OPEN;
+ }
+        case 314: break;
+        case 63: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction end");//$NON-NLS-1$
+        yybegin(YYINITIAL);
+        return XML_PI_CLOSE;
+ }
+        case 315: break;
+        case 57: 
+        case 59: 
+        case 60: 
+        case 61: 
+        case 137: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction attribute value");//$NON-NLS-1$
+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 316: break;
+        case 56: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction '='");//$NON-NLS-1$
+        yybegin(ST_XML_PI_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 317: break;
+        case 55: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("XML processing instruction attribute name");//$NON-NLS-1$
+        yybegin(ST_XML_PI_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 318: break;
+        case 51: 
+        case 52: 
+        case 53: 
+          { 
+	// block scan until close is found
+	return doScan("?>", false, XML_PI_CONTENT, ST_XML_PI_TAG_CLOSE, ST_XML_PI_TAG_CLOSE);
+ }
+        case 319: break;
+        case 50: 
+          { 
+        yybegin(ST_PI_CONTENT);
+        return WHITE_SPACE;
+ }
+        case 320: break;
+        case 46: 
+        case 47: 
+        case 48: 
+        case 49: 
+        case 129: 
+        case 130: 
+        case 131: 
+        case 217: 
+        case 239: 
+        case 240: 
+        case 252: 
+        case 253: 
+        case 262: 
+        case 272: 
+        case 280: 
+        case 284: 
+        case 287: 
+        case 288: 
+        case 289: 
+        case 290: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("processing instruction target");//$NON-NLS-1$
+        yybegin(ST_PI_WS);
+        return XML_TAG_NAME;
+ }
+        case 321: break;
+        case 41: 
+        case 42: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("comment content");//$NON-NLS-1$
+	return scanXMLCommentText();
+ }
+        case 322: break;
+        case 40: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("LINE FEED");//$NON-NLS-1$
+	return WHITE_SPACE;
+ }
+        case 323: break;
+        case 0: 
+        case 31: 
+        case 122: 
+        case 124: 
+        case 207: 
+        case 208: 
+        case 236: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nXML content");//$NON-NLS-1$
+	return XML_CONTENT;
+ }
+        case 324: break;
+        case 5: 
+        case 8: 
+        case 9: 
+        case 10: 
+        case 12: 
+        case 13: 
+        case 14: 
+        case 15: 
+        case 17: 
+        case 18: 
+        case 19: 
+        case 20: 
+        case 21: 
+        case 22: 
+        case 23: 
+        case 24: 
+        case 25: 
+        case 26: 
+        case 28: 
+        case 45: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("white space");//$NON-NLS-1$
+        return WHITE_SPACE;
+ }
+        case 325: break;
+        case 16: 
+        case 71: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("inappropriate tag name");//$NON-NLS-1$
+	yybegin(YYINITIAL);
+        return XML_CONTENT;
+ }
+        case 326: break;
+        case 27: 
+        case 106: 
+        case 107: 
+        case 193: 
+        case 229: 
+        case 248: 
+        case 259: 
+        case 269: 
+        case 277: 
+        case 281: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("elementdecl contentspec");//$NON-NLS-1$
+	return XML_ELEMENT_DECL_CONTENT;
+ }
+        case 327: break;
+        case 29: 
+        case 113: 
+        case 114: 
+        case 204: 
+        case 233: 
+        case 250: 
+        case 260: 
+        case 270: 
+        case 278: 
+        case 282: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist contentspec");//$NON-NLS-1$
+	return XML_ATTLIST_DECL_CONTENT;
+ }
+        case 328: break;
+        case 32: 
+        case 72: 
+        case 83: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nstart tag open");//$NON-NLS-1$
+        yybegin(ST_XML_TAG_NAME);
+        return XML_TAG_OPEN;
+ }
+        case 329: break;
+        case 33: 
+        case 34: 
+        case 37: 
+        case 38: 
+        case 39: 
+        case 43: 
+        case 44: 
+        case 54: 
+        case 58: 
+        case 62: 
+        case 64: 
+        case 68: 
+        case 74: 
+        case 80: 
+        case 85: 
+        case 86: 
+        case 87: 
+        case 88: 
+        case 90: 
+        case 91: 
+        case 93: 
+        case 98: 
+        case 103: 
+        case 110: 
+          { 
+	if (Debug.debugTokenizer)
+		System.out.println("!!!unexpected!!!: \"" + yytext() + "\":" + //$NON-NLS-2$//$NON-NLS-1$
+			yychar + "-" + (yychar + yylength()));//$NON-NLS-1$
+	return UNDEFINED;
+ }
+        case 330: break;
+        case 35: 
+        case 36: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("CDATA text");//$NON-NLS-1$
+	String blockContext = doBlockScan("]]>", XML_CDATA_TEXT, ST_CDATA_END);//$NON-NLS-1$
+	if(blockContext == XML_CDATA_TEXT)
+		yybegin(ST_CDATA_END);
+	return blockContext;
+ }
+        case 331: break;
+        case 65: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction attribute name");//$NON-NLS-1$
+        yybegin(ST_DHTML_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 332: break;
+        case 66: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction '='");//$NON-NLS-1$
+        yybegin(ST_DHTML_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 333: break;
+        case 67: 
+        case 69: 
+        case 70: 
+        case 145: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("DHTML processing instruction attribute value");//$NON-NLS-1$
+        yybegin(ST_DHTML_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 334: break;
+        case 73: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("tag close");//$NON-NLS-1$
+	if(isBlockMarker()) {
+        	yybegin(ST_BLOCK_TAG_SCAN);
+	}
+	else
+        	yybegin(YYINITIAL);
+        return XML_TAG_CLOSE;
+ }
+        case 335: break;
+        case 75: 
+        case 76: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("tag name");//$NON-NLS-1$
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+        return XML_TAG_NAME;
+ }
+        case 336: break;
+        case 77: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attr name");//$NON-NLS-1$
+        yybegin(ST_XML_EQUALS);
+        return XML_TAG_ATTRIBUTE_NAME;
+ }
+        case 337: break;
+        case 78: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("equals");//$NON-NLS-1$
+        yybegin(ST_XML_ATTRIBUTE_VALUE);
+        return XML_TAG_ATTRIBUTE_EQUALS;
+ }
+        case 338: break;
+        case 79: 
+        case 81: 
+        case 82: 
+        case 152: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attr value");//$NON-NLS-1$
+        yybegin(ST_XML_ATTRIBUTE_NAME);
+        return XML_TAG_ATTRIBUTE_VALUE;
+ }
+        case 339: break;
+        case 84: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("declaration end");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return XML_DECLARATION_CLOSE;
+ }
+        case 340: break;
+        case 89: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype type");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_EXTERNAL_ID);
+	return XML_DOCTYPE_NAME;
+ }
+        case 341: break;
+        case 92: 
+        case 94: 
+        case 95: 
+        case 96: 
+        case 166: 
+        case 167: 
+        case 170: 
+        case 171: 
+        case 224: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype public reference");//$NON-NLS-1$
+	yybegin(ST_XML_DOCTYPE_ID_SYSTEM);
+	return XML_DOCTYPE_EXTERNAL_ID_PUBREF;
+ }
+        case 342: break;
+        case 97: 
+        case 99: 
+        case 100: 
+        case 101: 
+        case 178: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("doctype system reference");//$NON-NLS-1$
+	yybegin(ST_XML_DECLARATION_CLOSE);
+	return XML_DOCTYPE_EXTERNAL_ID_SYSREF;
+ }
+        case 343: break;
+        case 102: 
+        case 104: 
+        case 105: 
+        case 186: 
+        case 187: 
+        case 190: 
+        case 191: 
+        case 227: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("elementdecl name");//$NON-NLS-1$
+	yybegin(ST_XML_ELEMENT_DECLARATION_CONTENT);
+	return XML_ELEMENT_DECL_NAME;
+ }
+        case 344: break;
+        case 108: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("elementdecl close");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return XML_DECLARATION_CLOSE;
+ }
+        case 345: break;
+        case 109: 
+        case 111: 
+        case 112: 
+        case 197: 
+        case 198: 
+        case 201: 
+        case 202: 
+        case 231: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist name");//$NON-NLS-1$
+	yybegin(ST_XML_ATTLIST_DECLARATION_CONTENT);
+	return XML_ATTLIST_DECL_NAME;
+ }
+        case 346: break;
+        case 115: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("attlist close");//$NON-NLS-1$
+	if (Debug.debugTokenizer) {
+		if(fStateStack.peek()!=YYINITIAL)
+			System.out.println("end embedded region");//$NON-NLS-1$
+	}
+	yybegin(fStateStack.pop());
+	return XML_DECLARATION_CLOSE;
+ }
+        case 347: break;
+        case 118: 
+          { 
+	if(Debug.debugTokenizer)
+		dump("\nend tag open");//$NON-NLS-1$
+        yybegin(ST_XML_TAG_NAME);
+        return XML_END_TAG_OPEN;
+ }
+        case 348: break;
+        case 116: 
+        case 117: 
+          { 
+		return doBlockTagScan();
+	 }
+        case 349: break;
+        default: 
+          if (yy_input == YYEOF && yy_startRead == yy_currentPos) {
+            yy_atEOF = true;
+            yy_do_eof();
+              return null;
+          } 
+          else {
+            yy_ScanError(YY_NO_MATCH);
+          }
+      }
+    }
+  }    
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/XMLTokenizer.jflex b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/XMLTokenizer.jflex
new file mode 100644
index 0000000..020e3e7
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/XMLTokenizer.jflex
@@ -0,0 +1,1332 @@
+/*******************************************************************************

+ * Copyright (c) 2004, 2010 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.wst.xml.core.internal.parser;

+

+import java.io.CharArrayReader;

+import java.io.IOException;

+import java.util.ArrayList;

+import java.util.Iterator;

+import java.util.List;

+

+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;

+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockTokenizer;

+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;

+import org.eclipse.wst.sse.core.internal.util.Debug;

+import org.eclipse.wst.sse.core.utils.StringUtils;

+import org.eclipse.wst.xml.core.internal.Logger;

+import org.eclipse.wst.xml.core.internal.parser.regions.XMLParserRegionFactory;

+import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;

+

+%%

+

+%{

+	private int fTokenCount = 0;

+ 

+	// required holders for white-space compacting

+	private boolean fShouldLoadBuffered = false;

+	private String fBufferedContext = null;

+	private int fBufferedStart = 1;

+	private int fBufferedLength = 0;

+	private String f_context = null;

+

+	// state stack for handling embedded regions

+	private IntStack fStateStack = new IntStack();

+

+	private String context = null;

+	private int start = 0;

+	private int textLength = 0;

+	private int length = 0;

+

+	// offset for tracking position specific block tags

+	private int fOffset = 0;

+	

+	// the name of the current tag being opened

+	private String fCurrentTagName = null;

+

+	// the list of tag name BlockMarkers

+	private List fBlockMarkers = new ArrayList();

+

+	// required to not seek text blocks on an end tag

+	private boolean fIsBlockingEnabled = false;

+	private boolean fIsCaseSensitiveBlocking = true;

+

+	private XMLParserRegionFactory fRegionFactory = new XMLParserRegionFactory();

+/**

+ * user method 

+ */

+public final void addBlockMarker(BlockMarker marker) {

+	if(containsTagName(marker.getTagName()))

+		return;

+	fBlockMarkers.add(marker);

+}

+/**

+ * user method 

+ */

+public final void removeBlockMarker(BlockMarker marker) {

+	fBlockMarkers.remove(marker);

+}

+/**

+ * user method 

+ */

+public final void removeBlockMarker(String tagname) {

+	if (fBlockMarkers != null) {

+		Iterator blocks = fBlockMarkers.iterator();

+		while (blocks.hasNext()) {

+			if (((BlockMarker) blocks.next()).getTagName().equals(tagname))

+				blocks.remove();

+		}

+	}

+}

+/* user method */

+public final boolean isCaseSensitiveBlocking() {

+	return fIsCaseSensitiveBlocking;

+}

+/* user method */

+public final void setCaseSensitiveBlocking(boolean newValue) {

+	fIsCaseSensitiveBlocking = newValue;

+}

+/* user method */

+public boolean getBlockMarkerCaseSensitivity() {

+        return getBlockMarkerCaseSensitivity(fCurrentTagName);

+}

+/* user method */

+public boolean getBlockMarkerCaseSensitivity(String name) {

+	Iterator iterator = fBlockMarkers.iterator();

+	while(iterator.hasNext()) {

+		BlockMarker marker = (BlockMarker)iterator.next();

+		boolean casesensitive = marker.isCaseSensitive();

+		if(casesensitive && marker.getTagName().equals(name))

+			return casesensitive;

+		else if(!casesensitive && marker.getTagName().equalsIgnoreCase(name))

+			return casesensitive;

+	}

+	return true;

+}

+/* user method */

+public String getBlockMarkerContext() {

+	return getBlockMarkerContext(fCurrentTagName);

+}

+/* user method */

+public String getBlockMarkerContext(String name) {

+	Iterator iterator = fBlockMarkers.iterator();

+	while(iterator.hasNext()) {

+		BlockMarker marker = (BlockMarker)iterator.next();

+		if(marker.getTagName().equals(name))

+			return marker.getContext();

+	}

+	return BLOCK_TEXT;

+}

+/* user method */

+public List getBlockMarkers() {

+	return fBlockMarkers;

+}

+/* user method */

+public final int getOffset() {

+	return fOffset + yychar;

+}

+private final boolean isBlockMarker() {

+	return isBlockMarker(fCurrentTagName);

+}

+private final boolean isBlockMarker(String tagName) {

+	if (!fIsBlockingEnabled)

+		return false;

+	return containsTagName(tagName);

+}

+/**

+ * user method

+ */

+public final void beginBlockTagScan(String newTagName) {

+	beginBlockMarkerScan(newTagName, BLOCK_TEXT);

+}

+/**

+ * user method

+ *

+ * Special tokenizer setup.  Allows tokenization to be initiated at the

+ * start of a text block within a "newTagName" tag.

+ *

+ * Example: 

+ *	Tokenizer toker = new Tokenizer();

+ *	toker.setCaseSensitiveBlocking(false);

+ *	toker.reset(new java.io.StringReader("afiuhqwkejhtasihgalkwhtq</scripter></scr></script>asgdasga"));

+ *	toker.beginBlockMarkerScan("script", BLOCK_TEXT);

+ *	toker.getRegions(); 

+ *

+ * Returns:

+ *	BLOCK_TEXT: 0-40

+ *	XML_END_TAG_OPEN: 41-42

+ *	XML_TAG_NAME: 43-48

+ *	XML_TAG_CLOSE: 49-49

+ *	XML_CONTENT: 50-57

+ *

+ */

+public final void beginBlockMarkerScan(String newTagName, String blockcontext) {

+	yybegin(ST_BLOCK_TAG_SCAN);

+	fCurrentTagName = newTagName;

+}

+/**

+ * Method doScan.

+ * 

+ * Returns a context region for all of the text from the current position upto the end of input or

+ * to right *before* the first occurence of searchString

+ * 

+ * @param searchString - target string to search for ex.: "-->", "</tagname"

+ * @param requireTailSeparator - whether the target must be immediately followed by whitespace or '>'

+ * @param context - the context of the scanned region if non-zero length

+ * @param exitState - the state to go to if the region was of non-zero length

+ * @param abortState - the state to go to if the searchString was found immediately

+ * @return String - the context found: the desired context on a non-zero length match, the abortContext on immediate success

+ * @throws IOException

+ */

+private final String doScan(String searchString, boolean requireTailSeparator, String searchContext, int exitState, int immediateFallbackState) throws IOException {

+	boolean stillSearching = true;

+	// Disable further block (probably)

+	fIsBlockingEnabled = false;

+	int searchStringLength = searchString.length();

+	int n = 0;

+	char lastCheckChar;

+	int i;

+	boolean same = false;

+	while (stillSearching) {

+		n = 0;

+		// Ensure that enough data from the input exists to compare against the search String.

+		n = yy_advance();

+		while(n != YYEOF && yy_currentPos < searchStringLength)

+			n = yy_advance();

+		// If the input was too short or we've exhausted the input, stop immediately.

+		if (n == YYEOF) {

+			stillSearching = false;

+		}

+		else {

+			same = true;

+			// Ensure that we've not encountered a complete block (<%%>) that was *shorter* than the closeTagString and

+			// thus found twice at current-targetLength [since the first scan would have come out this far anyway].

+			// Check the characters in the target versus the last targetLength characters read from the buffer

+			// and see if it matches

+			

+			// safety check for array accesses (yy_currentPos is the *last* character we can check against)

+			if(yy_currentPos >= searchStringLength && yy_currentPos <= yy_buffer.length) {

+				for(i = 0; i < searchStringLength; i++) {

+					if(same && fIsCaseSensitiveBlocking)

+						same = yy_buffer[i + yy_currentPos - searchStringLength] == searchString.charAt(i);

+					else if(same && !fIsCaseSensitiveBlocking)

+						same = Character.toLowerCase(yy_buffer[i + yy_currentPos - searchStringLength]) == Character.toLowerCase(searchString.charAt(i));

+				}

+			}

+			// safety check failed; no match is possible right now

+			else {

+				same = false;

+			}

+			if (same && requireTailSeparator && yy_currentPos < yy_buffer.length) {

+				// Additional check for close tags to ensure that targetString="</script" doesn't match

+				// "</scriptS"

+				lastCheckChar = yy_buffer[yy_currentPos];

+				// Succeed on "</script>" and "</script "

+				if(lastCheckChar == '>' || Character.isWhitespace(lastCheckChar))

+					stillSearching = false;

+			}

+			else {

+				stillSearching = !same || (yy_currentPos < yy_startRead + searchStringLength);

+			}

+		}

+	}

+	if (n != YYEOF || same) {

+		// We've stopped short of the end or definitely found a match

+		yy_markedPos = yy_currentPos - searchStringLength;

+		yy_currentPos = yy_markedPos + 1;

+		// If the searchString occurs at the very beginning of what would have

+		// been a Block, resume scanning normally immediately

+		if (yy_markedPos == yy_startRead) {

+			yybegin(immediateFallbackState);

+			return primGetNextToken();

+		}

+	}

+	else {

+		// We ran through the rest of the input

+		yy_markedPos = yy_currentPos;

+		yy_currentPos++;

+	}

+	yybegin(exitState);

+	// If the ending occurs at the very beginning of what would have

+	// been a Block, resume scanning normally immediately

+	if(yy_markedPos == yy_startRead)

+		return primGetNextToken();

+	return searchContext;

+}

+/**

+ * user method

+ *

+ * A generic lookahead-like operation

+ */

+private final String doBlockScan(String target, String targetContext, int immediateFallbackState) throws IOException {

+	return doScan(target, false, targetContext, immediateFallbackState, immediateFallbackState);

+}

+/**

+ * user method 

+ * does a lookahead for the current tag name

+ */

+private final String doBlockTagScan() throws IOException {

+        fIsCaseSensitiveBlocking = getBlockMarkerCaseSensitivity();

+	return doScan("</" + fCurrentTagName, true, getBlockMarkerContext(fCurrentTagName), YYINITIAL, YYINITIAL);

+}

+/**

+ * user method

+ *

+ * Converts the raw context String returned by the primGetNextToken()

+ * method into a full ITextRegion by pulling in values for the

+ * current offset within the scanning text.

+ *

+ * Returns null when EOF is encountered and attaches intermittently

+ * discovered whitespace onto the end of useful regions.

+ *

+ * Note that this algorithm caches the token following the one being returned

+ * so that whitespace can be collapsed.

+ */

+public final ITextRegion getNextToken() throws IOException {

+	// load the starting non-whitespace token (assume that it is so)

+	if (fShouldLoadBuffered) {

+		context = fBufferedContext;

+		start = fBufferedStart;

+		textLength = length = fBufferedLength;

+		fShouldLoadBuffered = false;

+	}

+	else {

+		context = primGetNextToken();

+		if (context == XML_TAG_NAME) {

+			if(containsTagName(yy_buffer, yy_startRead, yy_markedPos-yy_startRead))

+				fCurrentTagName = yytext();

+			else

+				fCurrentTagName = null;

+		}

+		else if (context == XML_TAG_OPEN) {

+			fIsBlockingEnabled = true;

+		}

+		else if (context == XML_END_TAG_OPEN) {

+			fIsBlockingEnabled = false;

+		}

+		start = yychar;

+		textLength = length = yylength();

+		if (yy_atEOF) {

+			fTokenCount++;

+			return null;

+		}

+	}

+	// store the next token

+	f_context = primGetNextToken();

+	if (f_context == XML_TAG_NAME) {

+		if(containsTagName(yy_buffer, yy_startRead, yy_markedPos-yy_startRead))

+			fCurrentTagName = yytext();

+		else

+			fCurrentTagName = null;

+	}

+	else if (f_context == XML_TAG_OPEN) {

+		fIsBlockingEnabled = true;

+	}

+	else if (f_context == XML_END_TAG_OPEN) {

+		fIsBlockingEnabled = false;

+	}

+	fBufferedContext = f_context;

+	fBufferedStart = yychar;

+	fBufferedLength = yylength();

+	fShouldLoadBuffered = true;

+	if (fBufferedContext == WHITE_SPACE) {

+		fShouldLoadBuffered = false;

+		length += fBufferedLength;

+	}

+	if (context == null) {

+		// EOF

+		if (Debug.debugTokenizer) {

+			System.out.println(getClass().getName() + " discovered " + fTokenCount + " tokens."); //$NON-NLS-2$//$NON-NLS-1$

+		}

+		return null;

+	}

+	fTokenCount++;

+	return fRegionFactory.createToken(context, start, textLength, length, null, fCurrentTagName);

+}

+/* user method */

+public XMLTokenizer(){

+	super();

+}

+/* user method */

+public XMLTokenizer(char[] charArray){

+		this(new CharArrayReader(charArray));

+}

+/* user method */

+public void reset(char[] charArray) {

+	reset(new CharArrayReader(charArray), 0);

+}

+/* user method */

+public void reset(char[] charArray, int newOffset) {

+	reset(new CharArrayReader(charArray), newOffset);

+}

+/* user method */

+public void reset(java.io.InputStream in) {

+	reset(new java.io.InputStreamReader(in), 0);

+}

+/* user method */

+public void reset(java.io.InputStream in, int newOffset) {

+	reset(new java.io.InputStreamReader(in), newOffset);

+}

+/* user method */

+public void reset(java.io.Reader in) {

+	reset(in, 0);

+}

+/**

+ * user method *

+ *

+ * Reset internal counters and vars to "newly created" values, in the hopes

+ * that resetting a pre-existing tokenizer is faster than creating a new one.

+ *

+ * This method contains code blocks that were essentially duplicated from the

+ * <em>generated</em> output of this specification before this method was

+ * added.  Those code blocks were under the above copyright.

+ */

+public void reset(java.io.Reader in, int newOffset) {

+	if (Debug.debugTokenizer) {

+		System.out.println("resetting tokenizer");//$NON-NLS-1$

+	}

+	fOffset = newOffset;

+

+	/* the input device */

+	yy_reader = in;

+

+	/* the current state of the DFA */

+	yy_state = 0;

+

+	/* the current lexical state */

+	yy_lexical_state = YYINITIAL;

+

+	/* this buffer contains the current text to be matched and is

+	the source of the yytext() string */

+	java.util.Arrays.fill(yy_buffer, (char)0);

+

+	/* the textposition at the last accepting state */

+	yy_markedPos = 0;

+

+	/* the textposition at the last state to be included in yytext */

+	//yy_pushbackPos = 0;

+

+	/* the current text position in the buffer */

+	yy_currentPos = 0;

+

+	/* startRead marks the beginning of the yytext() string in the buffer */

+	yy_startRead = 0;

+

+	/** 

+	 * endRead marks the last character in the buffer, that has been read

+	 * from input 

+	 */

+	yy_endRead = 0;

+

+	/* number of newlines encountered up to the start of the matched text */

+	//yyline = 0;

+

+	/* the number of characters up to the start of the matched text */

+	yychar = 0;

+

+	/* yy_atEOF == true <=> the scanner has returned a value for EOF */

+	yy_atEOF = false;

+

+	/* denotes if the user-EOF-code has already been executed */

+	yy_eof_done = false;

+

+

+	/* user vars: */

+	fTokenCount = 0;

+ 

+	fShouldLoadBuffered = false;

+	fBufferedContext = null;

+	fBufferedStart = 1;

+	fBufferedLength = 0;

+	fStateStack = new IntStack();

+

+	context = null;

+	start = 0;

+	textLength = 0;

+	length = 0;

+}

+

+	/**

+	 * user method

+	 *

+	 */

+	public BlockTokenizer newInstance() {

+		XMLTokenizer newInstance = new XMLTokenizer();

+		// global tagmarkers can be shared; they have no state and 

+		// are never destroyed (e.g. 'release')

+		for(int i = 0; i < fBlockMarkers.size(); i++) {

+			BlockMarker blockMarker = (BlockMarker) fBlockMarkers.get(i);

+			if(blockMarker.isGlobal())

+				newInstance.addBlockMarker(blockMarker);

+		}

+		return newInstance;

+	}

+/* user method */

+private final String scanXMLCommentText() throws IOException {

+	// Scan for '-->' and return the text up to that point as

+	//   XML_COMMENT_TEXT unless the string occurs IMMEDIATELY, in which

+	//  case change to the ST_XML_COMMENT_END state and return the next

+	//  context as usual.

+	return doScan("-->", false, XML_COMMENT_TEXT, ST_XML_COMMENT_END, ST_XML_COMMENT_END);

+}

+%}

+

+%eof{

+// do nothing, this is the downstream parser's job

+%eof}

+

+%public

+%class XMLTokenizer

+%implements BlockTokenizer, DOMRegionContext

+%function primGetNextToken

+%type String

+%char

+%unicode

+%pack

+

+%state ST_CDATA_TEXT

+%state ST_CDATA_END

+%state ST_XML_COMMENT

+%state ST_XML_COMMENT_END

+%state ST_PI

+%state ST_PI_WS

+%state ST_PI_CONTENT

+%state ST_XML_PI_ATTRIBUTE_NAME

+%state ST_XML_PI_EQUALS

+%state ST_XML_PI_ATTRIBUTE_VALUE

+%state ST_XML_PI_TAG_CLOSE

+%state ST_DHTML_ATTRIBUTE_NAME

+%state ST_DHTML_EQUALS

+%state ST_DHTML_ATTRIBUTE_VALUE

+%state ST_DHTML_TAG_CLOSE

+

+// normal tag states

+%state ST_XML_TAG_NAME

+%state ST_XML_ATTRIBUTE_NAME

+%state ST_XML_EQUALS

+%state ST_XML_ATTRIBUTE_VALUE

+

+// declaration (DTD) states

+%state ST_XML_DECLARATION

+%state ST_XML_DECLARATION_CLOSE

+

+%state ST_XML_DOCTYPE_DECLARATION

+%state ST_XML_DOCTYPE_EXTERNAL_ID

+%state ST_XML_DOCTYPE_ID_PUBLIC

+%state ST_XML_DOCTYPE_ID_SYSTEM

+

+%state ST_XML_ELEMENT_DECLARATION

+%state ST_XML_ELEMENT_DECLARATION_CONTENT

+

+%state ST_XML_ATTLIST_DECLARATION

+%state ST_XML_ATTLIST_DECLARATION_CONTENT

+

+%state ST_BLOCK_TAG_SCAN

+

+// Letter = ([A-Za-z])

+// Digit = ([0-9])

+

+/**

+ * smaller tokens

+ */

+genericTagOpen       = <

+genericTagClose      = >

+genericEndTagOpen    = <\/

+genericEmptyTagClose = \/>

+

+PIstart = <\?

+PIend   = \?>

+

+

+// [1] document ::= prolog element Misc*

+document = ({prolog} {element} {Misc}*)

+

+// [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]

+ //Char = (.)

+Char = [\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD] 

+

+// [3] S ::= (0x20 | 0x9 | 0xD | 0xA)+

+S = [\x20\x09\x0D\x0A]+

+

+// [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender

+NameChar = ({Letter} | {Digit} | \. | \- | _ | : | {CombiningChar} | {Extender})

+

+// [5] Name ::= (Letter | '_' | ':') NameChar*

+//Name = ({NameChar}{NameChar}*)

+Name = ({Letter} | _ | :){NameChar}*

+

+// [6] Names ::= {Name} ({S} {Name})*

+Names = ({Name} ({S} {Name})*)

+

+// [7] Nmtoken ::= (NameChar)+

+Nmtoken = ({NameChar}+)

+

+// [8] Nmtokens ::= Nmtoken (S Nmtoken)*

+Nmtokens = ({Nmtoken} ({S} {Nmtoken})*)

+

+// [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |  "'" ([^%&'] | PEReference | Reference)* "'"

+EntityValue = (\" ([^%&\"] | {PEReference} | {Reference})* \" |  \' ([^%&\'] | {PEReference} | {Reference})* \')

+

+// [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |  "'" ([^<&'] | Reference)* "'"

+AttValue = ( \" ([^\"] | {Reference})* \" | \' ([^\'] | {Reference})* \'  | ([^\'\"\040\011\012\015<>/]|\/+[^\'\"\040\011\012\015<>/] )* )

+

+// [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") 

+SystemLiteral = ((\" [^\"]* \") | (\' [^\']* \')) 

+

+// [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"

+PubidLiteral = (\" {PubidChar}* \" | \' ({PubidChar}\')* "'")

+

+// [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]

+PubidChar = ([\040\015\012] | [a-zA-Z0-9] | [\-\'()\+,.\/:=?;!\*#@\$_%])

+

+// [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)

+// implement lookahead behavior during action definition

+CharData = ([^<&(\]\]>)]*)

+

+// [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'

+CommentStart = (<!\-\-)

+CommentEnd   = (\-\->)

+Comment = ({CommentStart}.*{CommentEnd})

+

+// [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'

+PI = (<\?{PITarget} {Char}* \?>)

+

+// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))

+PITarget = ({Name}((X|x)(M|m)(L|l)))

+

+// [18] CDSect ::= CDStart CData CDEnd

+CDSect = ({CDStart}{CData}{CDEnd})

+

+// [19] CDStart ::= '<![CDATA['

+CDStart = <!\[CDATA\[

+

+// [20] CData ::= (Char* - (Char* ']]>' Char*)) 

+// implement lookahead behavior during action definition

+CData = ([^(\]\]>)]*)

+

+// [21] CDEnd ::= ']]>'

+CDEnd = (\]\]>)

+

+// [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?

+prolog = ({XMLDecl}? {Misc}* ({doctypedecl} {Misc}*)?)

+

+// [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'

+XMLDecl = (<\?xml {VersionInfo} {EncodingDecl}? {SDDecl}? {S}? \?>)

+

+// [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")

+VersionInfo = ({S}version{Eq}(\'{VersionNum}\' | \"{VersionNum}\"))

+

+// [25] Eq ::= S? '=' S?

+Eq = (\=)

+

+// [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+

+VersionNum = (([a-zA-Z0-9_.:]|\-)+)

+

+// [27] Misc ::= Comment | PI |  S

+Misc = ({Comment} | {PI} | {S})

+

+// [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)?  S? ('[' (markupdecl | PEReference | S)* ']' S?)? '>'

+doctypedecl = (<\!DOCTYPE{S}{Name} ({S}{ExternalID})? {S}? (\[ ({markupdecl}|{PEReference}|{S})* \]{S}?)?>)

+

+// [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment

+markupdecl = ({elementdecl} | {AttlistDecl} | {EntityDecl} | {NotationDecl} | {PI} | {Comment})

+

+// [30] extSubset ::= TextDecl? extSubsetDecl

+extSubset = ({TextDecl}? {extSubsetDecl})

+

+// [31] extSubsetDecl ::= ( markupdecl | conditionalSect | PEReference | S )*

+extSubsetDecl = (( {markupdecl} | {conditionalSect} | {PEReference} | {S} )*)

+

+// [32]  SDDecl  ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"'))

+SDDecl  = ({S}standalone{Eq}{S}*((\'(yes|no)\')|(\"(yes|no)\")))

+

+// [33]  LanguageID  ::= Langcode ('-' Subcode)*

+LanguageID  = ({Langcode}(\-{Subcode})*)

+

+// [34]  Langcode ::= ISO639Code |  IanaCode |  UserCode

+Langcode = ({ISO639Code} |  {IanaCode} |  {UserCode})

+

+// [35]  ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])

+ISO639Code = (([a-z]|[A-Z])([a-z]|[A-Z]))

+

+// [36]  IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+

+IanaCode = ((i|I)\-([a-z]|[A-Z])+)

+

+// [37]  UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+

+UserCode = ((x|X)\-([a-z]|[A-Z])+)

+

+// [38]  Subcode ::= ([a-z] | [A-Z])+

+Subcode = (([a-z]|[A-Z])+)

+

+// [39]  element  ::= EmptyElemTag | STag content ETag

+element  = ({EmptyElemTag} | {STag} {content} {ETag})

+

+// [40]  STag  ::= '<' Name (S Attribute)* S? '>'

+STag = (<{Name}({S}{Attribute})*{S}?>)

+

+// [41]  Attribute ::= Name Eq AttValue

+Attribute = ({Name}{S}*{Eq}{S}*{AttValue})

+

+// [42]  ETag  ::= 'Name S? '>'

+ETag = (<\/{Name}{S}?>)

+

+// [43]  content  ::= (element | CharData | Reference | CDSect | PI | Comment)*

+content = (({element} | {CharData} | {Reference} | {CDSect} | {PI} | {Comment})*)

+

+// [44]  EmptyElemTag  ::= '<' Name (S Attribute)* S? '/>'

+EmptyElemTag = (<{Name}({S}{Attribute})*{S}?\/>)

+

+// [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'

+elementdecl = (<\!ELEMENT{S}{Name}{S}{contentspec}{S}?>)

+

+// [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children

+contentspec = (EMPTY|ANY|{Mixed}|{children})

+

+// [47] children ::= (choice | seq) ('?' | '*' | '+')?

+children = (({choice}|{seq})(\?|\*|\+)?)

+

+// CAUSES LOOP THROUGH DEFS OF CHOICE AND SEQ

+// [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?

+cp = (({Name} | {choice} | {seq}) (\?|\*|\+)?)

+

+// [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'

+// choice = \({S}?{cp}({S}?\|{S}?{cp})*{S}?\)

+choice = \({S}?{Name}({S}?\|{S}?{Name})*{S}?\)

+

+// [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'

+// seq = (\({S}?{cp}({S}?\,{S}?{cp})*{S}?\))

+seq = (\({S}?{Name}({S}?\,{S}?{Name})*{S}?\))

+

+// [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S?  ')*' | '(' S? '#PCDATA' S? ')'

+Mixed = ({S}?\#PCDATA({S}?\|{S}?{Name})*{S}?)*\|({S}?\#PCDATA{S}?)

+

+// [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'

+AttlistDecl = (<\!ATTLIST{S}{Name}{AttDef}*{S}?>)

+

+// [53] AttDef ::= S Name S AttType S DefaultDecl

+AttDef = ({S}{Name}{S}{AttType}{S}{DefaultDecl})

+

+// [54] AttType ::= StringType | TokenizedType | EnumeratedType 

+AttType = ({StringType} | {TokenizedType} | {EnumeratedType})

+

+// [55] StringType ::= 'CDATA'

+StringType = (CDATA)

+

+// [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'

+TokenizedType = (ID|IDREF|IDREFS|ENTITY|ENTITIES|NMTOKEN|NMTOKENS)

+

+// [57] EnumeratedType ::= NotationType | Enumeration 

+EnumeratedType = ({NotationType} | {Enumeration})

+

+// [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')' 

+NotationType = (NOTATION{S}\({S}?{Name}({S}?\|{S}?{Name})*{S}?\))

+

+// [59] Enumeration ::= '(' S? Nmtoken (S? '|' S?  Nmtoken)* S? ')'

+Enumeration = (\({S}?{Nmtoken}({S}?\|{S}?{Nmtoken})*{S}?\))

+

+// [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)

+DefaultDecl = (\#REQUIRED|\#IMPLIED|((\#FIXED{S})?{AttValue}))

+

+// [61] conditionalSect ::= includeSect | ignoreSect 

+conditionalSect = ({includeSect} | {ignoreSect})

+

+// [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>' 

+includeSect = (<\!\[{S}?INCLUDE{S}?\[{extSubsetDecl}\]\]>)

+

+// [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'

+ignoreSect = (<\!\[{S}?IGNORE{S}?\[{ignoreSectContents}*\]\]>)

+

+// [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*

+ignoreSectContents = ({Ignore}(<\!\[{ignoreSectContents}\]\]>{Ignore})*)

+

+// [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)

+Ignore =  ([^(\<\!\[|\]\]\>)]*)

+

+// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'

+CharRef = (&#[0-9]+;|&#x[0-9a-fA-F]+;)

+

+// [67] Reference ::= EntityRef | CharRef

+Reference = ({EntityRef} | {CharRef})

+

+// [68] EntityRef = '&' Name ';'

+EntityRef = (&{Name};)

+

+// [69] PEReference ::= '%' Name ';'

+PEReference = (%{Name};)

+

+// [70] EntityDecl ::= GEDecl | PEDecl

+EntityDecl = ({GEDecl} | {PEDecl})

+

+// [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'

+GEDecl = (<\!ENTITY{S}{Name}{S}{EntityDef}{S}?>)

+

+// [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'

+PEDecl = (<\!ENTITY{S}\%{S}{Name}{S}{PEDef}{S}?>)

+

+// [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)

+EntityDef = ({EntityValue} | ({ExternalID}{NDataDecl}?))

+

+// [74] PEDef ::= EntityValue | ExternalID

+PEDef = ({EntityValue} | {ExternalID})

+

+// [75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral 

+ExternalID = (SYSTEM{S}{SystemLiteral}|PUBLIC{S}{PubidLiteral}{S}{SystemLiteral} )

+

+// [76] NDataDecl ::= S 'NDATA' S Name

+NDataDecl = ({S}NDATA{S}{Name})

+

+// [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'

+TextDecl = (<\?xml{VersionInfo}?{EncodingDecl}{S}?\?>)

+

+// [78] extParsedEnt ::= TextDecl? content

+extParsedEnt = ({TextDecl}?{content})

+

+// [79] extPE ::= TextDecl? extSubsetDecl

+extPE = ({TextDecl}?{extSubsetDecl})

+

+// [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'" ) 

+EncodingDecl = ({S}encoding{S}*{Eq}{S}*(\"{EncName}\"|\'{EncName}\'))

+

+// [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*

+EncName = ([A-Za-z]([A-Za-z0-9._]|\-)*)

+

+// [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'

+NotationDecl = (<\!NOTATION{S}{Name}{S}({ExternalID}|{PublicID}){S}?>)

+

+// [83] PublicID ::= 'PUBLIC' S PubidLiteral

+PublicID = (PUBLIC{S}{PubidLiteral})

+

+// [84]  Letter ::= BaseChar | Ideographic

+Letter = ({BaseChar} | {Ideographic})

+

+// [85]  BaseChar ::= [#x0041-#x005A] | [#x0061-#x007A] | [#x00C0-#x00D6]

+// | [#x00D8-#x00F6] | [#x00F8-#x00FF] | [#x0100-#x0131]

+// | [#x0134-#x013E] | [#x0141-#x0148] | [#x014A-#x017E]

+// | [#x0180-#x01C3] | [#x01CD-#x01F0] | [#x01F4-#x01F5]

+// | [#x01FA-#x0217] | [#x0250-#x02A8] | [#x02BB-#x02C1] | #x0386

+// | [#x0388-#x038A] | #x038C | [#x038E-#x03A1] | [#x03A3-#x03CE]

+// | [#x03D0-#x03D6] | #x03DA | #x03DC | #x03DE | #x03E0

+// | [#x03E2-#x03F3] | [#x0401-#x040C] | [#x040E-#x044F]

+// | [#x0451-#x045C] | [#x045E-#x0481] | [#x0490-#x04C4]

+// | [#x04C7-#x04C8] | [#x04CB-#x04CC] | [#x04D0-#x04EB]

+// | [#x04EE-#x04F5] | [#x04F8-#x04F9] | [#x0531-#x0556] | #x0559

+// | [#x0561-#x0586] | [#x05D0-#x05EA] | [#x05F0-#x05F2]

+// | [#x0621-#x063A] | [#x0641-#x064A] | [#x0671-#x06B7]

+// | [#x06BA-#x06BE] | [#x06C0-#x06CE] | [#x06D0-#x06D3] | #x06D5

+// | [#x06E5-#x06E6] | [#x0905-#x0939] | #x093D | [#x0958-#x0961]

+// | [#x0985-#x098C] | [#x098F-#x0990] | [#x0993-#x09A8]

+// | [#x09AA-#x09B0] | #x09B2 | [#x09B6-#x09B9] | [#x09DC-#x09DD]

+// | [#x09DF-#x09E1] | [#x09F0-#x09F1] | [#x0A05-#x0A0A]

+// | [#x0A0F-#x0A10] | [#x0A13-#x0A28] | [#x0A2A-#x0A30]

+// | [#x0A32-#x0A33] | [#x0A35-#x0A36] | [#x0A38-#x0A39]

+// | [#x0A59-#x0A5C] | #x0A5E | [#x0A72-#x0A74] | [#x0A85-#x0A8B]

+// | #x0A8D | [#x0A8F-#x0A91] | [#x0A93-#x0AA8] | [#x0AAA-#x0AB0]

+// | [#x0AB2-#x0AB3] | [#x0AB5-#x0AB9] | #x0ABD | #x0AE0

+// | [#x0B05-#x0B0C] | [#x0B0F-#x0B10] | [#x0B13-#x0B28]

+// | [#x0B2A-#x0B30] | [#x0B32-#x0B33] | [#x0B36-#x0B39] | #x0B3D

+// | [#x0B5C-#x0B5D] | [#x0B5F-#x0B61] | [#x0B85-#x0B8A]

+// | [#x0B8E-#x0B90] | [#x0B92-#x0B95] | [#x0B99-#x0B9A] | #x0B9C

+// | [#x0B9E-#x0B9F] | [#x0BA3-#x0BA4] | [#x0BA8-#x0BAA]

+// | [#x0BAE-#x0BB5] | [#x0BB7-#x0BB9] | [#x0C05-#x0C0C]

+// | [#x0C0E-#x0C10] | [#x0C12-#x0C28] | [#x0C2A-#x0C33]

+// | [#x0C35-#x0C39] | [#x0C60-#x0C61] | [#x0C85-#x0C8C]

+// | [#x0C8E-#x0C90] | [#x0C92-#x0CA8] | [#x0CAA-#x0CB3]

+// | [#x0CB5-#x0CB9] | #x0CDE | [#x0CE0-#x0CE1] | [#x0D05-#x0D0C]

+// | [#x0D0E-#x0D10] | [#x0D12-#x0D28] | [#x0D2A-#x0D39]

+// | [#x0D60-#x0D61] | [#x0E01-#x0E2E] | #x0E30 | [#x0E32-#x0E33]

+// | [#x0E40-#x0E45] | [#x0E81-#x0E82] | #x0E84 | [#x0E87-#x0E88]

+// | #x0E8A | #x0E8D | [#x0E94-#x0E97] | [#x0E99-#x0E9F]

+// | [#x0EA1-#x0EA3] | #x0EA5 | #x0EA7 | [#x0EAA-#x0EAB]

+// | [#x0EAD-#x0EAE] | #x0EB0 | [#x0EB2-#x0EB3] | #x0EBD

+// | [#x0EC0-#x0EC4] | [#x0F40-#x0F47] | [#x0F49-#x0F69]

+// | [#x10A0-#x10C5] | [#x10D0-#x10F6] | #x1100 | [#x1102-#x1103]

+// | [#x1105-#x1107] | #x1109 | [#x110B-#x110C] | [#x110E-#x1112]

+// | #x113C | #x113E | #x1140 | #x114C | #x114E | #x1150

+// | [#x1154-#x1155] | #x1159 | [#x115F-#x1161] | #x1163 | #x1165

+// | #x1167 | #x1169 | [#x116D-#x116E] | [#x1172-#x1173] | #x1175

+// | #x119E | #x11A8 | #x11AB | [#x11AE-#x11AF] | [#x11B7-#x11B8]

+// | #x11BA | [#x11BC-#x11C2] | #x11EB | #x11F0 | #x11F9

+// | [#x1E00-#x1E9B] | [#x1EA0-#x1EF9] | [#x1F00-#x1F15]

+// | [#x1F18-#x1F1D] | [#x1F20-#x1F45] | [#x1F48-#x1F4D]

+// | [#x1F50-#x1F57] | #x1F59 | #x1F5B | #x1F5D | [#x1F5F-#x1F7D]

+// | [#x1F80-#x1FB4] | [#x1FB6-#x1FBC] | #x1FBE | [#x1FC2-#x1FC4]

+// | [#x1FC6-#x1FCC] | [#x1FD0-#x1FD3] | [#x1FD6-#x1FDB]

+// | [#x1FE0-#x1FEC] | [#x1FF2-#x1FF4] | [#x1FF6-#x1FFC] | #x2126

+// | [#x212A-#x212B] | #x212E | [#x2180-#x2182] | [#x3041-#x3094]

+// | [#x30A1-#x30FA] | [#x3105-#x312C] | [#xAC00-#xD7A3]

+BaseChar = [\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u0131\u0134-\u013E\u0141-\u0148\u014A-\u017E\u0180-\u01C3\u01CD-\u01F0\u01F4-\u01F5\u01FA-\u0217\u0250-\u02A8\u02BB-\u02C1\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03D6\u03DA\u03DC\u03DE\u03E0\u03E2-\u03F3\u0401-\u040C\u040E-\u044F\u0451-\u045C\u045E-\u0481\u0490-\u04C4\u04C7-\u04C8\u04CB-\u04CC\u04D0-\u04EB\u04EE-\u04F5\u04F8-\u04F9\u0531-\u0556\u0559\u0561-\u0586\u05D0-\u05EA\u05F0-\u05F2\u0621-\u063A\u0641-\u064A\u0671-\u06B7\u06BA-\u06BE\u06C0-\u06CE\u06D0-\u06D3\u06D5\u06E5-\u06E6\u0905-\u0939\u093D\u0958-\u0961\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8B\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AE0\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B36-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB5\u0BB7-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CDE\u0CE0-\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D60-\u0D61\u0E01-\u0E2E\u0E30\u0E32-\u0E33\u0E40-\u0E45\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EAE\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0F40-\u0F47\u0F49-\u0F69\u10A0-\u10C5\u10D0-\u10F6\u1100\u1102-\u1103\u1105-\u1107\u1109\u110B-\u110C\u110E-\u1112\u113C\u113E\u1140\u114C\u114E\u1150\u1154-\u1155\u1159\u115F-\u1161\u1163\u1165\u1167\u1169\u116D-\u116E\u1172-\u1173\u1175\u119E\u11A8\u11AB\u11AE-\u11AF\u11B7-\u11B8\u11BA\u11BC-\u11C2\u11EB\u11F0\u11F9\u1E00-\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2126\u212A-\u212B\u212E\u2180-\u2182\u3041-\u3094\u30A1-\u30FA\u3105-\u312C\uAC00-\uD7A3]

+

+// [86]  Ideographic ::= [#x4E00-#x9FA5] | #x3007 | [#x3021-#x3029]

+Ideographic = [\u4E00-\u9FA5\u3007\u3021-\u3029]

+

+// [87]      CombiningChar    ::=    [#x0300-#x0345]    | [#x0360-#x0361]

+// | [#x0483-#x0486]          | [#x0591-#x05A1]         | [#x05A3-#x05B9]

+// | [#x05BB-#x05BD]       | #x05BF       | [#x05C1-#x05C2]	 | #x05C4

+// | [#x064B-#x0652]    | #x0670    | [#x06D6-#x06DC]   | [#x06DD-#x06DF]

+// | [#x06E0-#x06E4]          | [#x06E7-#x06E8]         | [#x06EA-#x06ED]

+// | [#x0901-#x0903]       | #x093C       | [#x093E-#x094C]      | #x094D

+// | [#x0951-#x0954]    | [#x0962-#x0963]    | [#x0981-#x0983]   | #x09BC

+// | #x09BE       | #x09BF       | [#x09C0-#x09C4]      | [#x09C7-#x09C8]

+// | [#x09CB-#x09CD]   | #x09D7   | [#x09E2-#x09E3]   | #x0A02   | #x0A3C

+// | #x0A3E       | #x0A3F       | [#x0A40-#x0A42]      | [#x0A47-#x0A48]

+// | [#x0A4B-#x0A4D]    | [#x0A70-#x0A71]    | [#x0A81-#x0A83]   | #x0ABC

+// | [#x0ABE-#x0AC5]          | [#x0AC7-#x0AC9]         | [#x0ACB-#x0ACD]

+// | [#x0B01-#x0B03]    | #x0B3C    | [#x0B3E-#x0B43]   | [#x0B47-#x0B48]

+// | [#x0B4B-#x0B4D]          | [#x0B56-#x0B57]         | [#x0B82-#x0B83]

+// | [#x0BBE-#x0BC2]    | [#x0BC6-#x0BC8]    | [#x0BCA-#x0BCD]   | #x0BD7

+// | [#x0C01-#x0C03]          | [#x0C3E-#x0C44]         | [#x0C46-#x0C48]

+// | [#x0C4A-#x0C4D]          | [#x0C55-#x0C56]         | [#x0C82-#x0C83]

+// | [#x0CBE-#x0CC4]          | [#x0CC6-#x0CC8]         | [#x0CCA-#x0CCD]

+// | [#x0CD5-#x0CD6]          | [#x0D02-#x0D03]         | [#x0D3E-#x0D43]

+// | [#x0D46-#x0D48]       | [#x0D4A-#x0D4D]       | #x0D57      | #x0E31

+// | [#x0E34-#x0E3A]    | [#x0E47-#x0E4E]    | #x0EB1   | [#x0EB4-#x0EB9]

+// | [#x0EBB-#x0EBC]    | [#x0EC8-#x0ECD]    | [#x0F18-#x0F19]   | #x0F35

+// | #x0F37      | #x0F39     | #x0F3E     | #x0F3F     | [#x0F71-#x0F84]

+// | [#x0F86-#x0F8B]    | [#x0F90-#x0F95]    | #x0F97   | [#x0F99-#x0FAD]

+// | [#x0FB1-#x0FB7]       | #x0FB9       | [#x20D0-#x20DC]      | #x20E1

+// | [#x302A-#x302F] | #x3099 | #x309A

+CombiningChar =    [\u0300-\u0345\u0360-\u0361\u0483-\u0486\u0591-\u05A1\u05A3-\u05B9\u05BB-\u05BD\u05BF\u05C1-\u05C2\u05C4\u064B-\u0652\u0670\u06D6-\u06DC\u06DD-\u06DF\u06E0-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0901-\u0903\u093C\u093E-\u094C\u094D\u0951-\u0954\u0962-\u0963\u0981-\u0983\u09BC\u09BE\u09BF\u09C0-\u09C4\u09C7-\u09C8\u09CB-\u09CD\u09D7\u09E2-\u09E3\u0A02\u0A3C\u0A3E\u0A3F\u0A40-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A70-\u0A71\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0B01-\u0B03\u0B3C\u0B3E-\u0B43\u0B47-\u0B48\u0B4B-\u0B4D\u0B56-\u0B57\u0B82-\u0B83\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C01-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56\u0C82-\u0C83\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5-\u0CD6\u0D02-\u0D03\u0D3E-\u0D43\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86-\u0F8B\u0F90-\u0F95\u0F97\u0F99-\u0FAD\u0FB1-\u0FB7\u0FB9\u20D0-\u20DC\u20E1\u302A-\u302F\u3099\u309A]

+

+// [88]   Digit  ::=  [#x0030-#x0039] | [#x0660-#x0669] | [#x06F0-#x06F9]

+// | [#x0966-#x096F]          | [#x09E6-#x09EF]         | [#x0A66-#x0A6F]

+// | [#x0AE6-#x0AEF]          | [#x0B66-#x0B6F]         | [#x0BE7-#x0BEF]

+// | [#x0C66-#x0C6F]          | [#x0CE6-#x0CEF]         | [#x0D66-#x0D6F]

+// | [#x0E50-#x0E59] | [#x0ED0-#x0ED9] | [#x0F20-#x0F29]

+Digit =  [\u0030-\u0039\u0660-\u0669\u06F0-\u06F9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE7-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29]

+

+// [89]  Extender ::= #x00B7 | #x02D0 | #x02D1 | #x0387 | #x0640 | #x0E46

+// | #x0EC6       | #x3005       | [#x3031-#x3035]      | [#x309D-#x309E]

+// | [#x30FC-#x30FE]

+Extender = [\u00B7\u02D0\u02D1\u0387\u0640\u0E46\u0EC6\u3005\u3031-\u3035\u309D-\u309E\u30FC-\u30FE]

+

+%%

+

+

+/* white space within a tag */

+<ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_ATTRIBUTE_VALUE, ST_PI, ST_XML_PI_EQUALS, ST_XML_PI_ATTRIBUTE_NAME, ST_XML_PI_ATTRIBUTE_VALUE, ST_XML_DECLARATION, ST_XML_DOCTYPE_DECLARATION, ST_XML_ELEMENT_DECLARATION, ST_XML_ATTLIST_DECLARATION, ST_XML_DECLARATION_CLOSE, ST_XML_DOCTYPE_ID_PUBLIC, ST_XML_DOCTYPE_ID_SYSTEM, ST_XML_DOCTYPE_EXTERNAL_ID,ST_DHTML_ATTRIBUTE_NAME,ST_DHTML_EQUALS,ST_DHTML_ATTRIBUTE_VALUE,ST_DHTML_TAG_CLOSE> {S}* {

+	if(Debug.debugTokenizer)

+		dump("white space");//$NON-NLS-1$

+        return WHITE_SPACE;

+}

+

+// BEGIN REGULAR XML

+/* handle opening a new tag almost anywhere */

+<YYINITIAL, ST_XML_TAG_NAME, ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_DECLARATION, ST_XML_ATTRIBUTE_VALUE> {genericTagOpen} {

+	if(Debug.debugTokenizer)

+		dump("\nstart tag open");//$NON-NLS-1$

+        yybegin(ST_XML_TAG_NAME);

+        return XML_TAG_OPEN;

+}

+

+/* unquoted */

+

+<YYINITIAL, ST_XML_TAG_NAME, ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_ATTRIBUTE_VALUE, ST_XML_DECLARATION> {genericEndTagOpen} {

+	if(Debug.debugTokenizer)

+		dump("\nend tag open");//$NON-NLS-1$

+        yybegin(ST_XML_TAG_NAME);

+        return XML_END_TAG_OPEN;

+}

+/* the tag's name was found, start scanning for attributes */

+<ST_XML_TAG_NAME> {Name} {

+	if(Debug.debugTokenizer)

+		dump("tag name");//$NON-NLS-1$

+        yybegin(ST_XML_ATTRIBUTE_NAME);

+        return XML_TAG_NAME;

+}

+/* another attribute name was found, resume looking for the equals sign */

+<ST_XML_ATTRIBUTE_NAME, ST_XML_EQUALS> {Name} {

+	if(Debug.debugTokenizer)

+		dump("attr name");//$NON-NLS-1$

+        yybegin(ST_XML_EQUALS);

+        return XML_TAG_ATTRIBUTE_NAME;

+}

+/* an equal sign was found, what's next is the value */

+<ST_XML_EQUALS> {Eq} {

+	if(Debug.debugTokenizer)

+		dump("equals");//$NON-NLS-1$

+        yybegin(ST_XML_ATTRIBUTE_VALUE);

+        return XML_TAG_ATTRIBUTE_EQUALS;

+}

+/* the value was found, look for the next name */

+/* allow for unbalanced quotes, mostly a duplicate of the AttValue rule */

+<ST_XML_ATTRIBUTE_VALUE> {AttValue} | ([\'\"]([^\'\"\040\011\012\015<>/]|\/+[^\'\"\040\011\012\015<>/] )* ) {

+	if(Debug.debugTokenizer)

+		dump("attr value");//$NON-NLS-1$

+        yybegin(ST_XML_ATTRIBUTE_NAME);

+        return XML_TAG_ATTRIBUTE_VALUE;

+}

+

+

+/* the tag's close was found */

+<ST_XML_TAG_NAME, ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_ATTRIBUTE_VALUE> {genericTagClose} {

+	if(Debug.debugTokenizer)

+		dump("tag close");//$NON-NLS-1$

+	if(isBlockMarker()) {

+        	yybegin(ST_BLOCK_TAG_SCAN);

+	}

+	else

+        	yybegin(YYINITIAL);

+        return XML_TAG_CLOSE;

+}

+/* the tag's close was found, but the tag doesn't need a matching end tag */

+<ST_XML_TAG_NAME, ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_ATTRIBUTE_VALUE> {genericEmptyTagClose} {

+        yybegin(YYINITIAL);

+	if(Debug.debugTokenizer)

+		dump("empty tag close");//$NON-NLS-1$

+        return XML_EMPTY_TAG_CLOSE;

+}

+

+<ST_XML_TAG_NAME> [^</>\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u0131\u0134-\u013E\u0141-\u0148\u014A-\u017E\u0180-\u01C3\u01CD-\u01F0\u01F4-\u01F5\u01FA-\u0217\u0250-\u02A8\u02BB-\u02C1\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03D6\u03DA\u03DC\u03DE\u03E0\u03E2-\u03F3\u0401-\u040C\u040E-\u044F\u0451-\u045C\u045E-\u0481\u0490-\u04C4\u04C7-\u04C8\u04CB-\u04CC\u04D0-\u04EB\u04EE-\u04F5\u04F8-\u04F9\u0531-\u0556\u0559\u0561-\u0586\u05D0-\u05EA\u05F0-\u05F2\u0621-\u063A\u0641-\u064A\u0671-\u06B7\u06BA-\u06BE\u06C0-\u06CE\u06D0-\u06D3\u06D5\u06E5-\u06E6\u0905-\u0939\u093D\u0958-\u0961\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8B\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AE0\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B36-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB5\u0BB7-\u0BB9\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CDE\u0CE0-\u0CE1\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D60-\u0D61\u0E01-\u0E2E\u0E30\u0E32-\u0E33\u0E40-\u0E45\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EAE\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0F40-\u0F47\u0F49-\u0F69\u10A0-\u10C5\u10D0-\u10F6\u1100\u1102-\u1103\u1105-\u1107\u1109\u110B-\u110C\u110E-\u1112\u113C\u113E\u1140\u114C\u114E\u1150\u1154-\u1155\u1159\u115F-\u1161\u1163\u1165\u1167\u1169\u116D-\u116E\u1172-\u1173\u1175\u119E\u11A8\u11AB\u11AE-\u11AF\u11B7-\u11B8\u11BA\u11BC-\u11C2\u11EB\u11F0\u11F9\u1E00-\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2126\u212A-\u212B\u212E\u2180-\u2182\u3041-\u3094\u30A1-\u30FA\u3105-\u312C\uAC00-\uD7A3\u4E00-\u9FA5\u3007\u3021-\u3029]* {

+	if(Debug.debugTokenizer)

+		dump("inappropriate tag name");//$NON-NLS-1$

+	yybegin(YYINITIAL);

+        return XML_CONTENT;

+}

+

+// END REGULAR XML

+

+

+// XML Comments

+

+<YYINITIAL, ST_XML_TAG_NAME, ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_ATTRIBUTE_VALUE, ST_XML_DECLARATION> {CommentStart} {

+	if(Debug.debugTokenizer)

+		dump("\ncomment start");//$NON-NLS-1$

+	yybegin(ST_XML_COMMENT);

+	return XML_COMMENT_OPEN;

+}

+<ST_XML_COMMENT> .|\r|\n {

+	if(Debug.debugTokenizer)

+		dump("comment content");//$NON-NLS-1$

+	return scanXMLCommentText();

+}

+

+<ST_XML_COMMENT_END> {CommentEnd} {

+	if(Debug.debugTokenizer)

+		dump("comment end");//$NON-NLS-1$

+	yybegin(YYINITIAL);

+	return XML_COMMENT_CLOSE;

+}

+

+// XML misc

+

+{CDStart} {

+	if(Debug.debugTokenizer)

+		dump("\nCDATA start");//$NON-NLS-1$

+	fStateStack.push(yystate());

+	yybegin(ST_CDATA_TEXT);

+	return XML_CDATA_OPEN;

+}

+<ST_CDATA_TEXT> .|\r|\n {

+	if(Debug.debugTokenizer)

+		dump("CDATA text");//$NON-NLS-1$

+	String blockContext = doBlockScan("]]>", XML_CDATA_TEXT, ST_CDATA_END);//$NON-NLS-1$

+	if(blockContext == XML_CDATA_TEXT)

+		yybegin(ST_CDATA_END);

+	return blockContext;

+}

+<ST_CDATA_END> {CDEnd} {

+	if(Debug.debugTokenizer)

+		dump("CDATA end");//$NON-NLS-1$

+	yybegin(fStateStack.pop());

+	return XML_CDATA_CLOSE;

+}

+

+<YYINITIAL> {PEReference} {

+	if(Debug.debugTokenizer)

+		dump("\nPEReference");//$NON-NLS-1$

+	return XML_PE_REFERENCE;

+}

+<YYINITIAL> {CharRef} {

+	if(Debug.debugTokenizer)

+		dump("\nCharRef");//$NON-NLS-1$

+	return XML_CHAR_REFERENCE;

+}

+<YYINITIAL> {EntityRef} {

+	if(Debug.debugTokenizer)

+		dump("\nEntityRef");//$NON-NLS-1$

+	return XML_ENTITY_REFERENCE;

+}

+

+<YYINITIAL> {PIstart} {

+	if(Debug.debugTokenizer)

+		dump("\nprocessing instruction start");//$NON-NLS-1$

+	yybegin(ST_PI);

+        return XML_PI_OPEN;

+}

+// the next four are order dependent

+<ST_PI> ((X|x)(M|m)(L|l)) {

+	if(Debug.debugTokenizer)

+		dump("XML processing instruction target");//$NON-NLS-1$

+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);

+        return XML_TAG_NAME;

+}

+<ST_PI> ([iI][mM][pP][oO][rR][tT]{S}*) {

+	if(Debug.debugTokenizer)

+		dump("DHTML processing instruction target");//$NON-NLS-1$

+        yybegin(ST_DHTML_ATTRIBUTE_NAME);

+        return XML_TAG_NAME;

+}

+<ST_PI> xml-stylesheet {

+	if(Debug.debugTokenizer)

+		dump("XSL processing instruction target");//$NON-NLS-1$

+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);

+        return XML_TAG_NAME;

+}

+<ST_PI> {Name} {

+	if(Debug.debugTokenizer)

+		dump("processing instruction target");//$NON-NLS-1$

+        yybegin(ST_PI_WS);

+        return XML_TAG_NAME;

+}

+<ST_PI_WS> {S}+ {

+        yybegin(ST_PI_CONTENT);

+        return WHITE_SPACE;

+}

+<ST_PI, ST_PI_WS> \?> {

+	if(Debug.debugTokenizer)

+		dump("processing instruction end");//$NON-NLS-1$

+        yybegin(YYINITIAL);

+        return XML_PI_CLOSE;

+}

+<ST_PI_CONTENT> . {

+	// block scan until close is found

+	return doScan("?>", false, XML_PI_CONTENT, ST_XML_PI_TAG_CLOSE, ST_XML_PI_TAG_CLOSE);

+}

+<ST_PI_CONTENT,ST_XML_PI_TAG_CLOSE> \?> {

+		// ended with nothing inside

+        yybegin(YYINITIAL);

+        return XML_PI_CLOSE;

+}

+<ST_XML_PI_ATTRIBUTE_NAME, ST_XML_PI_EQUALS> {Name} {

+	if(Debug.debugTokenizer)

+		dump("XML processing instruction attribute name");//$NON-NLS-1$

+        yybegin(ST_XML_PI_EQUALS);

+        return XML_TAG_ATTRIBUTE_NAME;

+}

+<ST_XML_PI_EQUALS> {Eq} {

+	if(Debug.debugTokenizer)

+		dump("XML processing instruction '='");//$NON-NLS-1$

+        yybegin(ST_XML_PI_ATTRIBUTE_VALUE);

+        return XML_TAG_ATTRIBUTE_EQUALS;

+}

+/* the value was found, look for the next name */

+<ST_XML_PI_ATTRIBUTE_VALUE> {AttValue} | ([\'\"]([^\'\"\040\011\012\015<>/]|\/+[^\'\"\040\011\012\015<>/] )* ) {

+	if(Debug.debugTokenizer)

+		dump("XML processing instruction attribute value");//$NON-NLS-1$

+        yybegin(ST_XML_PI_ATTRIBUTE_NAME);

+        return XML_TAG_ATTRIBUTE_VALUE;

+}

+/* the PI's close was found */

+<ST_XML_PI_EQUALS, ST_XML_PI_ATTRIBUTE_NAME, ST_XML_PI_ATTRIBUTE_VALUE> {PIend} {

+	if(Debug.debugTokenizer)

+		dump("XML processing instruction end");//$NON-NLS-1$

+        yybegin(YYINITIAL);

+        return XML_PI_CLOSE;

+}

+// DHTML

+<ST_DHTML_ATTRIBUTE_NAME, ST_DHTML_EQUALS> {Name} {

+	if(Debug.debugTokenizer)

+		dump("DHTML processing instruction attribute name");//$NON-NLS-1$

+        yybegin(ST_DHTML_EQUALS);

+        return XML_TAG_ATTRIBUTE_NAME;

+}

+<ST_DHTML_EQUALS> {Eq} {

+	if(Debug.debugTokenizer)

+		dump("DHTML processing instruction '='");//$NON-NLS-1$

+        yybegin(ST_DHTML_ATTRIBUTE_VALUE);

+        return XML_TAG_ATTRIBUTE_EQUALS;

+}

+/* the value was found, look for the next name */

+<ST_DHTML_ATTRIBUTE_VALUE> {AttValue} | ([\'\"]([^\'\"\040\011\012\015<>/]|\/+[^\'\"\040\011\012\015<>/] )* ) {

+	if(Debug.debugTokenizer)

+		dump("DHTML processing instruction attribute value");//$NON-NLS-1$

+        yybegin(ST_DHTML_ATTRIBUTE_NAME);

+        return XML_TAG_ATTRIBUTE_VALUE;

+}

+/* The DHTML PI's close was found */

+<ST_DHTML_EQUALS, ST_DHTML_ATTRIBUTE_NAME, ST_DHTML_ATTRIBUTE_VALUE> [/]*> {

+	if(Debug.debugTokenizer)

+		dump("DHTML processing instruction end");//$NON-NLS-1$

+        yybegin(YYINITIAL);

+        return XML_PI_CLOSE;

+}

+

+// XML declarations

+

+<YYINITIAL, ST_XML_TAG_NAME, ST_XML_EQUALS, ST_XML_ATTRIBUTE_NAME, ST_XML_ATTRIBUTE_VALUE> {genericTagOpen}! {

+	fStateStack.push(yystate());

+	if(Debug.debugTokenizer)

+		dump("\ndeclaration start");//$NON-NLS-1$

+        yybegin(ST_XML_DECLARATION);

+	return XML_DECLARATION_OPEN;

+}

+<ST_XML_DECLARATION> [Ee][Ll][Ee][Mm][Ee][Nn][Tt] {

+	if(Debug.debugTokenizer)

+		dump("element");//$NON-NLS-1$

+	yybegin(ST_XML_ELEMENT_DECLARATION);

+	return XML_ELEMENT_DECLARATION;

+}

+<ST_XML_DECLARATION> [Dd][Oo][Cc][Tt][Yy][Pp][Ee] {

+	if(Debug.debugTokenizer)

+		dump("doctype");//$NON-NLS-1$

+	yybegin(ST_XML_DOCTYPE_DECLARATION);

+	return XML_DOCTYPE_DECLARATION;

+}

+<ST_XML_DECLARATION> [Aa][Tt][Tt][Ll][Ii][Ss][Tt] {

+	if(Debug.debugTokenizer)

+		dump("attlist");//$NON-NLS-1$

+	yybegin(ST_XML_ATTLIST_DECLARATION);

+	return XML_ATTLIST_DECLARATION;

+}

+

+// begin DOCTYPE handling procedure

+<ST_XML_DOCTYPE_DECLARATION, ST_XML_DOCTYPE_EXTERNAL_ID, ST_XML_DOCTYPE_ID_SYSTEM, ST_XML_DOCTYPE_ID_PUBLIC, ST_XML_DECLARATION_CLOSE> \[[^\]]*\] {

+	return XML_DOCTYPE_INTERNAL_SUBSET;

+}

+

+<ST_XML_DOCTYPE_DECLARATION> {Name} {

+	if(Debug.debugTokenizer)

+		dump("doctype type");//$NON-NLS-1$

+	yybegin(ST_XML_DOCTYPE_EXTERNAL_ID);

+	return XML_DOCTYPE_NAME;

+}

+<ST_XML_DOCTYPE_EXTERNAL_ID> [Pp][Uu][Bb][Ll][Ii][Cc] {

+	if(Debug.debugTokenizer)

+		dump("doctype external id");//$NON-NLS-1$

+	yybegin(ST_XML_DOCTYPE_ID_PUBLIC);

+	return XML_DOCTYPE_EXTERNAL_ID_PUBLIC;

+}

+<ST_XML_DOCTYPE_EXTERNAL_ID> [Ss][Yy][Ss][Tt][Ee][Mm] {

+	if(Debug.debugTokenizer)

+		dump("doctype external id");//$NON-NLS-1$

+	yybegin(ST_XML_DOCTYPE_ID_SYSTEM);

+	return XML_DOCTYPE_EXTERNAL_ID_SYSTEM;

+}

+<ST_XML_DOCTYPE_ID_PUBLIC> {AttValue}|{PubidLiteral}|([\'\"]([^\'\"\040\011\012\015<>/]|\/+[^\'\"\040\011\012\015<>/] )* ) {

+	if(Debug.debugTokenizer)

+		dump("doctype public reference");//$NON-NLS-1$

+	yybegin(ST_XML_DOCTYPE_ID_SYSTEM);

+	return XML_DOCTYPE_EXTERNAL_ID_PUBREF;

+}

+<ST_XML_DOCTYPE_ID_SYSTEM> {AttValue}|{SystemLiteral}|([\'\"]([^\'\"\040\011\012\015<>/]|\/+[^\'\"\040\011\012\015<>/] )* ) {

+	if(Debug.debugTokenizer)

+		dump("doctype system reference");//$NON-NLS-1$

+	yybegin(ST_XML_DECLARATION_CLOSE);

+	return XML_DOCTYPE_EXTERNAL_ID_SYSREF;

+}

+// end DOCTYPE handling

+

+// begin ELEMENT handling procedure

+<ST_XML_ELEMENT_DECLARATION> {AttValue}|{PubidLiteral}|([\'\"]([^\'\"\040\011\012\015<>/]|\/+[^\'\"\040\011\012\015<>/] )* ) {

+	if(Debug.debugTokenizer)

+		dump("elementdecl name");//$NON-NLS-1$

+	yybegin(ST_XML_ELEMENT_DECLARATION_CONTENT);

+	return XML_ELEMENT_DECL_NAME;

+}

+<ST_XML_ELEMENT_DECLARATION_CONTENT> [^>]* {

+	if(Debug.debugTokenizer)

+		dump("elementdecl contentspec");//$NON-NLS-1$

+	return XML_ELEMENT_DECL_CONTENT;

+}

+

+<ST_XML_ELEMENT_DECLARATION_CONTENT> {genericTagClose} {

+	if(Debug.debugTokenizer)

+		dump("elementdecl close");//$NON-NLS-1$

+	if (Debug.debugTokenizer) {

+		if(fStateStack.peek()!=YYINITIAL)

+			System.out.println("end embedded region");//$NON-NLS-1$

+	}

+	yybegin(fStateStack.pop());

+	return XML_DECLARATION_CLOSE;

+}

+// end ELEMENT handling

+

+// begin ATTLIST handling procedure

+<ST_XML_ATTLIST_DECLARATION> {AttValue}|{PubidLiteral}|([\'\"]([^\'\"\040\011\012\015<>/]|\/+[^\'\"\040\011\012\015<>/] )* ) {

+	if(Debug.debugTokenizer)

+		dump("attlist name");//$NON-NLS-1$

+	yybegin(ST_XML_ATTLIST_DECLARATION_CONTENT);

+	return XML_ATTLIST_DECL_NAME;

+}

+<ST_XML_ATTLIST_DECLARATION_CONTENT> [^>]* {

+	if(Debug.debugTokenizer)

+		dump("attlist contentspec");//$NON-NLS-1$

+	return XML_ATTLIST_DECL_CONTENT;

+}

+

+<ST_XML_ATTLIST_DECLARATION_CONTENT> {genericTagClose} {

+	if(Debug.debugTokenizer)

+		dump("attlist close");//$NON-NLS-1$

+	if (Debug.debugTokenizer) {

+		if(fStateStack.peek()!=YYINITIAL)

+			System.out.println("end embedded region");//$NON-NLS-1$

+	}

+	yybegin(fStateStack.pop());

+	return XML_DECLARATION_CLOSE;

+}

+// end ATTLIST handling

+

+<ST_XML_DECLARATION, ST_XML_DOCTYPE_DECLARATION, ST_XML_DOCTYPE_EXTERNAL_ID, ST_XML_ATTLIST_DECLARATION, ST_XML_ELEMENT_DECLARATION, ST_XML_DECLARATION_CLOSE, ST_XML_DOCTYPE_ID_PUBLIC, ST_XML_DOCTYPE_ID_SYSTEM, ST_XML_DOCTYPE_EXTERNAL_ID> {genericTagClose} {

+	if(Debug.debugTokenizer)

+		dump("declaration end");//$NON-NLS-1$

+	if (Debug.debugTokenizer) {

+		if(fStateStack.peek()!=YYINITIAL)

+			System.out.println("end embedded region");//$NON-NLS-1$

+	}

+	yybegin(fStateStack.pop());

+	return XML_DECLARATION_CLOSE;

+}

+// end DECLARATION handling

+

+<YYINITIAL> [^<&%]*|[&%]{S}+{Name}[^&%<]*|[&%]{Name}([^;&%<]*|{S}+;*) {

+	if(Debug.debugTokenizer)

+		dump("\nXML content");//$NON-NLS-1$

+	return XML_CONTENT;

+}

+

+<YYINITIAL> (%)+ {

+	if(Debug.debugTokenizer)

+		dump("non-reference %");//$NON-NLS-1$

+	return XML_CONTENT;

+}

+

+<ST_BLOCK_TAG_SCAN> .|\r|\n {

+		return doBlockTagScan();

+	}

+

+. {

+	if (Debug.debugTokenizer)

+		System.out.println("!!!unexpected!!!: \"" + yytext() + "\":" + //$NON-NLS-2$//$NON-NLS-1$

+			yychar + "-" + (yychar + yylength()));//$NON-NLS-1$

+	return UNDEFINED;

+}

+

+\040 {

+	if(Debug.debugTokenizer)

+		dump("SPACE");//$NON-NLS-1$

+	return WHITE_SPACE;

+}

+\011 {

+	if(Debug.debugTokenizer)

+		dump("0x9");//$NON-NLS-1$

+	return WHITE_SPACE;

+}

+\015 

+{

+	if(Debug.debugTokenizer)

+		dump("CARRIAGE RETURN");//$NON-NLS-1$

+	return WHITE_SPACE;

+}

+\012 {

+	if(Debug.debugTokenizer)

+		dump("LINE FEED");//$NON-NLS-1$

+	return WHITE_SPACE;

+}

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/flex.cmd b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/flex.cmd
new file mode 100644
index 0000000..59e811c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/flex.cmd
@@ -0,0 +1,3 @@
+@echo off

+cmd /c flexx.cmd

+cmd /c flexj.cmd

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/flex.sh b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/flex.sh
new file mode 100644
index 0000000..5cb6e3b
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/flex.sh
@@ -0,0 +1,7 @@
+#!/bin/sh

+export PATH=$PATH:/opt/IBMJava2-131/bin/:/opt/IBMJava2-13/bin/:/opt/jdk1.4

+java -Xmx470000000 -cp JFlex/lib/sed-jflex.jar;. JFlex.Main JSPTokenizer.jflex -skel skeleton.sse

+java -Xmx470000000 -cp JFlex/lib/sed-jflex.jar;. JFlex.Main XMLTokenizer.jflex -skel skeleton.sse

+rm -f JSPTokenizer.java~ JSPTokenizer~ XMLTokenizer.java~ XMLTokenizer~

+cp -v XMLTokenizer.java ../../../../sedmodel/com/ibm/sed/parser/internal

+cp -v JSPTokenizer.java ../../../../sedmodel/com/ibm/sed/parser/internal

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/flexj.cmd b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/flexj.cmd
new file mode 100644
index 0000000..e010e35
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/flexj.cmd
@@ -0,0 +1,3 @@
+@echo off

+PATH=%PATH%;d:\jdk6_01\bin

+java -Xmx470000000 -cp d:\JFlex\1.2.2\lib\JFlex.jar;. JFlex.Main JSPTokenizer.jflex -skel skeleton.sse && rm -f JSPTokenizer.java~ JSPTokenizer~ && copy JSPTokenizer.java ..\..\..\..\..\org.eclipse.jst.jsp.core\src\org\eclipse\jst\jsp\core\internal\parser\\internal\JSPTokenizer.java

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/flexx.cmd b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/flexx.cmd
new file mode 100644
index 0000000..fcb1f81
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/flexx.cmd
@@ -0,0 +1,3 @@
+@echo off

+PATH=%PATH%;c:\jdk1.4.2_08\bin

+java -Xmx470000000 -cp d:\JFlex\1.2.2\lib\JFlex.jar;. JFlex.Main XMLTokenizer.jflex -skel skeleton.sse && rm -f XMLTokenizer.java~ XMLTokenizer~ && copy XMLTokenizer.java ..\..\..\..\..\org.eclipse.wst.xml.core\src\org\eclipse\wst\xml\core\internal\parser\XMLTokenizer.java

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/skeleton.sse b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/skeleton.sse
new file mode 100644
index 0000000..3e1d3c4
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/skeleton.sse
@@ -0,0 +1,351 @@
+

+  /** this character denotes the end of file */

+  final public static int YYEOF = -1;

+

+  /** lexical states */

+---  lexical states, charmap

+

+  /* error codes */

+  final private static int YY_UNKNOWN_ERROR = 0;

+  // final private static int YY_ILLEGAL_STATE = 1;

+  final private static int YY_NO_MATCH = 2;

+  final private static int YY_PUSHBACK_2BIG = 3;

+

+  /* error messages for the codes above */

+  final private static String YY_ERROR_MSG[] = {

+    "Unkown internal scanner error",		//$NON-NLS-1$

+    "Internal error: unknown state",		//$NON-NLS-1$

+    "Error: could not match input",		//$NON-NLS-1$

+    "Error: pushback value was too large"	//$NON-NLS-1$

+  };

+

+--- isFinal list

+  /** the input device */

+  private java.io.Reader yy_reader;

+

+  /** the current state of the DFA */

+  private int yy_state;

+

+  /** the current lexical state */

+  private int yy_lexical_state = YYINITIAL;

+

+  /** this buffer contains the current text to be matched and is

+      the source of the yytext() string */

+  private char yy_buffer[] = new char[16384];

+

+  /** the textposition at the last accepting state */

+  private int yy_markedPos;

+

+  /** the textposition at the last state to be included in yytext */

+  private int yy_pushbackPos;

+

+  /** the current text position in the buffer */

+  private int yy_currentPos;

+

+  /** startRead marks the beginning of the yytext() string in the buffer */

+  private int yy_startRead;

+

+  /** endRead marks the last character in the buffer, that has been read

+      from input */

+  private int yy_endRead;

+

+  /** number of newlines encountered up to the start of the matched text */

+  // private int yyline;

+

+  /** the number of characters up to the start of the matched text */

+  private int yychar;

+

+  /**

+   * the number of characters from the last newline up to the start of the 

+   * matched text

+   */

+  // private int yycolumn; 

+

+  /** 

+   * yy_atBOL == true <=> the scanner is currently at the beginning of a line

+   */

+  // private boolean yy_atBOL;

+

+  /** yy_atEOF == true <=> the scanner has returned a value for EOF */

+  private boolean yy_atEOF;

+

+--- user class code

+

+  /**

+   * Creates a new scanner

+   * There is also a java.io.InputStream version of this constructor.

+   *

+   * @param   in  the java.io.Reader to read input from.

+   */

+--- constructor declaration

+

+

+  /**

+   * Gets the next input character.

+   *

+   * @return      the next character of the input stream, EOF if the

+   *              end of the stream is reached.

+   * @exception   IOException  if any I/O-Error occurs

+   */

+  private int yy_advance() throws java.io.IOException {

+

+    /* standard case */

+    if (yy_currentPos < yy_endRead) return yy_buffer[yy_currentPos++];

+

+    /* if the eof is reached, we don't need to work hard */ 

+    if (yy_atEOF) return YYEOF;

+

+    /* otherwise: need to refill the buffer */

+

+    /* first: make room (if you can) */

+    if (yy_startRead > 0) {

+      System.arraycopy(yy_buffer, yy_startRead, 

+                       yy_buffer, 0, 

+                       yy_endRead-yy_startRead);

+

+      /* translate stored positions */

+      yy_endRead-= yy_startRead;

+      yy_currentPos-= yy_startRead;

+      yy_markedPos-= yy_startRead;

+      yy_pushbackPos-= yy_startRead;

+      yy_startRead = 0;

+    }

+

+    /* is the buffer big enough? */

+    if (yy_currentPos >= yy_buffer.length) {

+      /* if not: blow it up */

+      char newBuffer[] = new char[yy_currentPos*2];

+      System.arraycopy(yy_buffer, 0, newBuffer, 0, yy_buffer.length);

+      yy_buffer = newBuffer;

+    }

+

+    /* finally: fill the buffer with new input */

+    int numRead = yy_reader.read(yy_buffer, yy_endRead, 

+                                            yy_buffer.length-yy_endRead);

+

+    if ( numRead == -1 ) return YYEOF;

+

+    yy_endRead+= numRead;

+

+    return yy_buffer[yy_currentPos++];

+  }

+

+    

+  /**

+   * Closes the input stream.

+   */

+  final public void yyclose() throws java.io.IOException {

+    yy_atEOF = true;            /* indicate end of file */

+    yy_endRead = yy_startRead;  /* invalidate buffer    */

+    yy_reader.close();

+  }

+

+

+  /**

+   * Returns the current lexical state.

+   */

+  final public int yystate() {

+    return yy_lexical_state;

+  }

+

+  /**

+   * Enters a new lexical state

+   *

+   * @param newState the new lexical state

+   */

+  final public void yybegin(int newState) {

+    yy_lexical_state = newState;

+  }

+

+

+  /**

+   * Returns the text matched by the current regular expression.

+   */

+  final public String yytext() {

+    return new String( yy_buffer, yy_startRead, yy_markedPos-yy_startRead );

+  }

+

+  /**

+   * Returns the length of the matched text region.

+   */

+  final public int yylength() {

+    return yy_markedPos-yy_startRead;

+  }

+

+

+  /**

+   * Reports an error that occured while scanning - from the SED JFlex skeleton

+   *

+   * @param   errorCode  the code of the errormessage to display

+   */

+  private void yy_ScanError(int errorCode) {

+    try {

+      Logger.log(Logger.ERROR, YY_ERROR_MSG[errorCode]);

+    }

+    catch (ArrayIndexOutOfBoundsException e) {

+      Logger.log(Logger.ERROR, YY_ERROR_MSG[YY_UNKNOWN_ERROR]);

+    }

+    // DO NOT EXIT the VM on an error

+    // System.exit(1);

+  } 

+

+

+  /**

+   * Pushes the specified amount of characters back into the input stream.

+   *

+   * They will be read again by then next call of the scanning method

+   *

+   * @param number  the number of characters to be read again.

+   *                This number must not be greater than yylength()!

+   */

+  void yypushback(int number) {

+    if ( number > yylength() )

+      yy_ScanError(YY_PUSHBACK_2BIG);

+

+    yy_markedPos -= number;

+  }

+

+	/**

+	 * user method - skeleton.sed

+	 */

+	protected final boolean containsTagName(char[] markerTagName, int offset, int tagnameLength) {

+		for(int j = 0; j < fBlockMarkers.size(); j++) {

+			BlockMarker marker = (BlockMarker)fBlockMarkers.get(j);

+			if(marker.getTagName().length() == tagnameLength) {

+				boolean matchesSoFar = true;

+				for(int i = 0; i < tagnameLength && matchesSoFar; i++) {

+					if(marker.isCaseSensitive()) {

+						if(marker.getTagName().charAt(i) != markerTagName[i + offset])

+							matchesSoFar = false;

+					}

+					else {

+						if(Character.toLowerCase(marker.getTagName().charAt(i)) != Character.toLowerCase(markerTagName[i + offset]))

+							matchesSoFar = false;

+					}

+				}

+				if(matchesSoFar)

+					return true;

+			}

+		}

+		return false;

+	}

+

+	/**

+	 * user method - skeleton.sed

+	 *

+	 * Return ALL of the regions scannable within the remaining text

+	 * Note: for verification use

+	 */

+	public final List getRegions() {

+		List tokens = new ArrayList();

+		ITextRegion region = null;

+		try {

+			region = getNextToken();

+			while(region != null) {

+				if (region != null) {

+					tokens.add(region);

+				}

+				region = getNextToken();

+			}

+		}

+		catch (StackOverflowError e) {

+			Logger.logException(getClass().getName()+": input could not be tokenized correctly at position " + getOffset(), e);//$NON-NLS-1$

+			throw e;

+		}

+		catch (Exception e) {

+			// Since this is convenience method and NOT the recommended 

+			// way of getting tokens, many errors are simply hidden

+			Logger.logException("Exception not handled retrieving regions: " + e.getLocalizedMessage(), e);//$NON-NLS-1$

+		}

+		return tokens;

+	}

+	/**

+	 * user method - skeleton.sed

+	 */

+	private final void dump(String s) {

+		if (Debug.debugTokenizer) {

+			System.out.println(s + " (" + yychar + "-" + //$NON-NLS-2$//$NON-NLS-1$

+				(yylength() + yychar) + "):\'" +//$NON-NLS-1$

+					StringUtils.escape(yytext()) + "\'");//$NON-NLS-1$

+		}

+	}

+	/* user method  - skeleton.sed */

+	public final boolean isEOF() {

+		return yy_atEOF;

+	}

+/* user method - skeleton.sed */

+protected final boolean containsTagName(String markerTagName) {

+	Iterator blocks = fBlockMarkers.iterator();

+	while(blocks.hasNext()) {

+		BlockMarker marker = (BlockMarker)blocks.next();

+		if(marker.isCaseSensitive()) {

+			if(marker.getTagName().equals(markerTagName))

+				return true;

+		}

+		else {

+			if(marker.getTagName().equalsIgnoreCase(markerTagName))

+				return true;

+		}

+	}

+	return false;

+}

+

+--- yy_doEof

+  /**

+   * Resumes scanning until the next regular expression is matched,

+   * the end of input is encountered or an I/O-Error occurs.

+   *

+   * @return      the next token

+   * @exception   IOException  if any I/O-Error occurs

+   */

+--- yylex declaration

+    int yy_input;

+    int yy_action;

+

+--- local declarations

+

+    while (true) {

+

+--- start admin (line, char, col count)

+      yy_action = -1;

+

+      yy_currentPos = yy_startRead = yy_markedPos;

+

+--- start admin (lexstate etc)

+

+      yy_forAction: {

+        while (true) {

+    

+          yy_input = yy_advance();

+

+          if ( yy_input == YYEOF ) break yy_forAction;

+

+--- line, col, char count, next transition, isFinal action

+            yy_action = yy_state; 

+            yy_markedPos = yy_currentPos; 

+--- line count update

+          }

+

+        }

+      }

+

+--- char count update

+

+      switch (yy_action) {    

+

+--- actions

+        default: 

+          if (yy_input == YYEOF && yy_startRead == yy_currentPos) {

+            yy_atEOF = true;

+--- eofvalue

+          } 

+          else {

+--- no match

+          }

+      }

+    }

+  }    

+

+--- main

+

+}

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/skeleton.sse.readme b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/skeleton.sse.readme
new file mode 100644
index 0000000..eb89700
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/SedModel/HTMLTokenizer/devel/skeleton.sse.readme
@@ -0,0 +1,6 @@
+The skeleton.sed file contains the modified JFlex 1.2.2 skeleton file with

+changes for use with the tokenizers within the org.eclipse.wst.sse.core.xml and

+org.eclipse.wst.sse.core.jsp plugins.

+

+The skeleton file's method definitions are copied into the generated output

+directly.

diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/build.xml b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/build.xml
new file mode 100644
index 0000000..bfd83de
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/build.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="tokenizer" default="CSSTokenizer">
+	<target name="init" depends="properties">
+		<property name="workspace.dir" value="../.."/>
+		<property name="jflex.jar" value="/DevTimeSupport/JFlex/lib/sed-jflex.jar"/>
+		<property name="jflex.maxmemory" value="470000000"/>
+		<property name="jflex.opt" value="-skel SedModel/HTMLTokenizer/devel/skeleton.sse"/>
+	</target>
+
+	<target name="properties" if="eclipse.running">
+		<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
+	</target>
+
+	<target name="CSSTokenizer" depends="init">
+		<property name="src.dir" value="SedModel/CSSTokenizer/devel"/>
+		<property name="src.file" value="CSSTokenizer.jflex"/>			
+		<property name="dest.dir" value="org.eclipse.wst.sse.core.css/src/com/ibm/sse/model/css/internal/parser"/>
+		<property name="finaldest.dir" value="org.eclipse.wst.css.core/src/org/eclipse/wst/css/core/internal/parser"/>
+		<antcall target="build-tokenizer">
+			<param name="jflex.opt" value=""/>
+		</antcall>
+	</target>
+
+	<target name="XMLTokenizer" depends="init">
+		<property name="src.dir" value="SedModel/HTMLTokenizer/devel"/>
+		<property name="src.file" value="XMLTokenizer"/>			
+		<property name="dest.dir" value="org.eclipse.wst.sse.core.xml/src/com/ibm/sse/model/xml/internal/parser"/>
+		<antcall target="build-tokenizer"/>
+	</target>
+
+	<target name="JSPTokenizer" depends="init">
+		<property name="src.dir" value="SedModel/HTMLTokenizer/devel"/>
+		<property name="src.file" value="JSPTokenizer.jflex"/>			
+		<property name="dest.dir" value="org.eclipse.wst.sse.core.jsp/src/com/ibm/sse/model/jsp/parser/internal"/>
+		<antcall target="build-tokenizer"/>
+	</target>
+
+	<target name="build-tokenizer" depends="init">
+		<antcall target="run-jflex"/>
+		<antcall target="copy"/>
+		<antcall target="clean"/>
+	</target>
+
+	<target name="run-jflex" depends="init">
+		<java classname="JFlex.Main" maxmemory="${jflex.maxmemory}" fork="yes" >
+			<arg line="${src.dir}/${src.file} ${jflex.opt}"/>
+			<classpath>
+				<pathelement location="${jflex.jar}"/>
+			</classpath>
+		</java>
+	</target>
+	
+	<target name="copy" depends="init">
+		<copy todir="${workspace.dir}/${dest.dir}" overwrite="true" verbose="true">
+			<fileset dir="${src.dir}">
+				<include name="*.java"/>
+			</fileset>
+		</copy>
+		<copy todir="${workspace.dir}/${finaldest.dir}" overwrite="true" verbose="true">
+			<fileset dir="${src.dir}">
+				<include name="*.java"/>
+			</fileset>
+		</copy>
+	</target>
+	
+	<target name="clean" depends="init">
+		<delete verbose="true">
+			<fileset dir="${src.dir}" defaultexcludes="no">
+				<include name="*~"/>
+			</fileset>
+		</delete>
+	</target>
+	
+
+</project>
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.sse.core/DevTimeSupport/devTimeSupportInfo.txt b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/devTimeSupportInfo.txt
new file mode 100644
index 0000000..d8c776e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/DevTimeSupport/devTimeSupportInfo.txt
@@ -0,0 +1,15 @@
+
+
+This directory, DevTimeSupport, normally contains
+the source for some of our parser generators. 
+
+See :pserver:dev.eclipse.org:/cvsroot/webtools/sourceediting/plugins/org.eclipse.wst.sse.core/DevTimeSupport
+
+This particular text file you are reading 
+is the only one shipped 
+with an SDK build, since the other files 
+are seldom needed during development or debugging, 
+and some of those files cause problems with long 
+filename or paths that end up being too long for 
+some platforms, and some unzip programs. 
+
diff --git a/bundles/org.eclipse.wst.sse.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.sse.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..bee3db0
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/META-INF/MANIFEST.MF
@@ -0,0 +1,54 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.wst.sse.core; singleton:=true
+Bundle-Version: 1.1.602.qualifier
+Bundle-Activator: org.eclipse.wst.sse.core.internal.SSECorePlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.wst.sse.core,
+ org.eclipse.wst.sse.core.indexing,
+ org.eclipse.wst.sse.core.internal;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.cleanup;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.document;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.encoding;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.encoding.util;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.exceptions;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.filebuffers;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.format;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.ltk.modelhandler;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.ltk.parser;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.model;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.modelhandler;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.parser;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.preferences;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.provisional;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.provisional.document;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.provisional.events;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.provisional.exceptions;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.provisional.model;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.provisional.tasks;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.provisional.text;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.tasks;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.text;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.text.rules;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.undo;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.util;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.internal.validate;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui",
+ org.eclipse.wst.sse.core.text,
+ org.eclipse.wst.sse.core.utils,
+ org.eclipse.wst.sse.internal.contentproperties;x-friends:="org.eclipse.wst.dtd.core,org.eclipse.wst.dtd.ui,org.eclipse.wst.sse.ui,org.eclipse.wst.xml.core,org.eclipse.wst.xml.ui,org.eclipse.wst.xsd.core,org.eclipse.wst.xsd.ui"
+Import-Package: com.ibm.icu.util; version="3.8",
+ com.ibm.icu.text; version="3.8"
+Require-Bundle: org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.text;bundle-version="[3.5.0,4.0.0)";visibility:=reexport,
+ org.eclipse.core.jobs;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.core.filebuffers;bundle-version="[3.5.0,4.0.0)",
+ org.eclipse.wst.common.uriresolver;bundle-version="[1.1.301,1.2.0)",
+ org.eclipse.emf.common;bundle-version="[2.4.0,3.0.0)",
+ org.eclipse.wst.validation;bundle-version="[1.2.100,2.0.0)";resolution:=optional,
+ org.eclipse.core.expressions;bundle-version="[3.4.100,4.0.0)",
+ org.eclipse.osgi.services;bundle-version="3.2.0"
+Bundle-ActivationPolicy: lazy;exclude:="org.eclipse.wst.sse.core.internal.propertytester"
+Bundle-RequiredExecutionEnvironment: J2SE-1.4
diff --git a/bundles/org.eclipse.wst.sse.core/README.txt b/bundles/org.eclipse.wst.sse.core/README.txt
new file mode 100644
index 0000000..4eb3ccf
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/README.txt
@@ -0,0 +1,2 @@
+The core model of the sse framework. It provides the base document classes,
+builders and parsers.
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.sse.core/about.html b/bundles/org.eclipse.wst.sse.core/about.html
new file mode 100644
index 0000000..2199df3
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/about.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+
+<head>
+<title>About</title>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+</head>
+
+<BODY lang="EN-US">
+
+<H3>About This Content</H3>
+
+<P>June, 2008</P>
+
+<H3>License</H3>
+
+<P>The Eclipse Foundation makes available all content in this plug-in 
+("Content"). Unless otherwise indicated below, the Content is provided to you 
+under the terms and conditions of the Eclipse Public License Version 1.0 
+("EPL"). A copy of the EPL is available at
+<A href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/org/documents/epl-v10.php</A>. 
+For purposes of the EPL, "Program" will mean the Content.</P>
+
+<P>If you did not receive this Content directly from the Eclipse Foundation, the 
+Content is being redistributed by another party ("Redistributor") and different 
+terms and conditions may apply to your use of any object code in the Content. 
+Check the RedistributorÂ’s license that was provided with the Content. If no such 
+license exists, contact the Redistributor. Unless otherwise indicated below, the 
+terms and conditions of the EPL still apply to any source code in the Content 
+and such source code may be obtained at
+<A href="http://www.eclipse.org/">http://www.eclipse.org/</A>.</P>
+
+</BODY>
+</HTML>
diff --git a/bundles/org.eclipse.wst.sse.core/build.properties b/bundles/org.eclipse.wst.sse.core/build.properties
new file mode 100644
index 0000000..37541b2
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/build.properties
@@ -0,0 +1,34 @@
+###############################################################################
+# Copyright (c) 2001, 2006 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+#     Jens Lukowski/Innoopract - initial renaming/restructuring
+#     
+###############################################################################
+source.. = src-encoding/,\
+           src/,\
+           src-tasktags/,\
+           src-contentproperties/
+bin.includes = plugin.xml,\
+               plugin.properties,\
+               .options,\
+               config/,\
+               META-INF/,\
+               .,\
+               about.html
+bin.excludes = bin/**,\
+               @dot/**,\
+               temp.folder/**
+src.includes = schema/,\
+               doc/,\
+               component.xml,\
+               DevTimeSupport/
+output.. = bin/
+src.excludes = DevTimeSupport/build.xml,\
+               DevTimeSupport/SedModel/,\
+               DevTimeSupport/HeadParsers/
diff --git a/bundles/org.eclipse.wst.sse.core/component.xml b/bundles/org.eclipse.wst.sse.core/component.xml
new file mode 100644
index 0000000..dae223c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/component.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<component xmlns="http://eclipse.org/wtp/releng/tools/component-model" name="org.eclipse.wst.sse">
+	<description url="http://eclipse.org/webtools/wst/components/sse/overview.html"></description>
+	<component-depends unrestricted="true"></component-depends>
+	<plugin id="org.eclipse.wst.sse.core" fragment="false" />
+	<plugin id="org.eclipse.wst.sse.doc.user" fragment="false" />
+	<plugin id="org.eclipse.wst.sse.ui" fragment="false" />
+	<package name="org.eclipse.wst.sse.ui.views.properties" api="false">
+		<type name="PropertySheetConfiguration" subclass="true" instantiate="true" />
+		<type name="IPropertySourceExtension" implement="true" />
+	</package>
+	<package name="org.eclipse.wst.sse.ui" api="false">
+		<type name="StructuredTextEditor" subclass="false" instantiate="true" />
+		<type name="StructuredTextViewerConfiguration" subclass="true" instantiate="true" />
+	</package>
+	<package name="org.eclipse.wst.sse.ui.views.contentoutline" api="false">
+		<type name="ContentOutlineConfiguration" subclass="true" instantiate="true" />
+	</package>
+	<plugin id="org.eclipse.wst.sse.ui.infopop" fragment="false" />
+</component>
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.sse.core/config/charset.properties b/bundles/org.eclipse.wst.sse.core/config/charset.properties
new file mode 100644
index 0000000..881c97e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/config/charset.properties
@@ -0,0 +1,100 @@
+###############################################################################
+# Copyright (c) 2001, 2011 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
+###############################################################################
+! the number of codeset names
+totalnumber=26
+
+! Only translate the xx.label strings.  Do not translate the xx.iana, xx.prefName or xx.java strings.
+
+codeset.0.label=ISO 10646/Unicode(UTF-8)
+codeset.0.iana=UTF-8
+
+codeset.1.label=ISO 10646/Unicode(UTF-16) Big Endian
+codeset.1.iana=UTF-16
+
+codeset.2.label=ISO 10646/Unicode(UTF-16BE) Big Endian
+codeset.2.iana=UTF-16BE
+
+codeset.3.label=ISO 10646/Unicode(UTF-16LE) Little Endian
+codeset.3.iana=UTF-16LE
+
+codeset.4.label=US ASCII
+codeset.4.iana=US-ASCII
+
+codeset.5.label=ISO Latin-1
+codeset.5.iana=ISO-8859-1
+
+codeset.6.label=ISO Latin-9
+codeset.6.iana=ISO-8859-15
+
+! (Slavic: Czech, Croat, German, Hungarian, Polish, Romanian, Slovak, Slovenian)
+codeset.7.label=Central/East European (Slavic) 
+codeset.7.iana=ISO-8859-2
+
+! (Esperanto, Galician, Maltese, Turkish)
+codeset.8.label=Southern European
+codeset.8.iana=ISO-8859-3
+
+codeset.9.label=Arabic, Logical
+codeset.9.iana=ISO-8859-6
+
+codeset.10.label=Arabic
+codeset.10.iana=windows-1256
+
+codeset.11.label=Chinese, National Standard
+codeset.11.iana=GB18030
+
+codeset.12.label=Traditional Chinese, Big5
+codeset.12.iana=BIG5
+
+! (Estonian, Latvian, Lithuanian)
+codeset.13.label=Cyrillic, ISO-8859-4
+codeset.13.iana=ISO-8859-4
+
+! (Bulgarian, Byelorussian, Macedonian, Serbian, Ukrainian)
+codeset.14.label=Cyrillic, ISO-8859-5
+codeset.14.iana=ISO-8859-5
+
+codeset.15.label=Greek
+codeset.15.iana=ISO-8859-7
+
+codeset.16.label=Hebrew, Visual
+codeset.16.iana=ISO-8859-8
+
+! label=Hebrew, Logical
+! iana=ISO-8859-8-I
+
+codeset.17.label=Hebrew
+codeset.17.iana=windows-1255
+
+codeset.18.label=Japanese, EUC-JP
+codeset.18.iana=EUC-JP
+
+codeset.19.label=Japanese, ISO 2022
+codeset.19.iana=ISO-2022-JP
+
+codeset.20.label=Japanese, Shift-JIS
+codeset.20.iana=Shift_JIS
+
+codeset.21.label=Japanese, Windows-31J
+codeset.21.iana=Windows-31J
+codeset.21.prefName=windows-31j
+
+codeset.22.label=Korean, EUC-KR
+codeset.22.iana=EUC-KR
+
+codeset.23.label=Korean, ISO 2022
+codeset.23.iana=ISO-2022-KR
+
+codeset.24.label=Thai, TISI
+codeset.24.iana=TIS-620
+
+codeset.25.label=Turkish
+codeset.25.iana=ISO-8859-9
diff --git a/bundles/org.eclipse.wst.sse.core/config/defaultIANA.properties b/bundles/org.eclipse.wst.sse.core/config/defaultIANA.properties
new file mode 100644
index 0000000..f47ed6e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/config/defaultIANA.properties
@@ -0,0 +1,26 @@
+###############################################################################
+# Copyright (c) 2001, 2006 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+# This file lists charset mappings between an encoding and its default
+# equivalent encoding listed in charset.properties
+# format: anyname=iana name listed in charset.properties
+
+# No translation necessary
+windows-1252=ISO-8859-1
+windows-932=Shift_JIS
+x-euc-jp-linux=EUC-JP 
+windows-949=EUC-KR
+x-windows-949=EUC-KR
+windows-950=BIG5
+x-windows-950=BIG5
+windows-936=GB18030
+x-mswin-936=GB18030
+GB2312=GB18030
+x-EUC-CN=GB18030
diff --git a/bundles/org.eclipse.wst.sse.core/config/override.properties b/bundles/org.eclipse.wst.sse.core/config/override.properties
new file mode 100644
index 0000000..ae703ba
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/config/override.properties
@@ -0,0 +1,24 @@
+###############################################################################
+# Copyright (c) 2001, 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
+#     Jens Lukowski/Innoopract - initial renaming/restructuring
+#     
+###############################################################################
+# This file lists charset mappings which supplement or override those
+# provided by the VM. There are few cases where this should be required.
+# Note: there is no integrety checking to see if the validCharsetName is indeed
+# valid for a given VM, so errors would only show up when attempted to 
+# be used.
+
+# No translation necessary
+
+# format: anyname=validjavaCharsetName
+ISO-8859-8-I=ISO-8859-8
+X-SJIS=Shift_JIS
+X-EUC-JP=Shift_JIS
diff --git a/bundles/org.eclipse.wst.sse.core/doc/book.css b/bundles/org.eclipse.wst.sse.core/doc/book.css
new file mode 100644
index 0000000..9278cd8
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/doc/book.css
@@ -0,0 +1,106 @@
+P.Code {

+	display: block;

+	text-align: left;

+	text-indent: 0.00pt;

+	margin-top: 0.000000pt;

+	margin-bottom: 0.000000pt;

+	margin-right: 0.000000pt;

+	margin-left: 15pt;

+	font-size: 10.000000pt;

+	font-weight: medium;

+	font-style: Regular;

+	color: #4444CC;

+	text-decoration: none;

+	vertical-align: baseline;

+	text-transform: none;

+	font-family: "Courier New";

+}

+H6.CaptionFigColumn {

+	display: block;

+	text-align: left;

+	text-indent: 0.000000pt;

+	margin-top: 3.000000pt;

+	margin-bottom: 11.000000pt;

+	margin-right: 0.000000pt;

+	margin-left: 0.000000pt;

+	font-size: 9.000000pt;

+	font-weight: medium;

+	font-style: Italic;

+	color: #000000;

+	text-decoration: none;

+	vertical-align: baseline;

+	text-transform: none;

+	font-family: "Arial";

+}

+P.Note {

+	display: block;

+	text-align: left;

+	text-indent: 0pt;

+	margin-top: 19.500000pt;

+	margin-bottom: 19.500000pt;

+	margin-right: 0.000000pt;

+	margin-left: 30pt;

+	font-size: 11.000000pt;

+	font-weight: medium;

+	font-style: Italic;

+	color: #000000;

+	text-decoration: none;

+	vertical-align: baseline;

+	text-transform: none;

+	font-family: "Arial";

+}

+EM.UILabel {

+	font-weight: Bold;

+	font-style: Regular;

+	text-decoration: none;

+	vertical-align: baseline;

+	text-transform: none;

+}

+EM.CodeName {

+	font-weight: Bold;

+	font-style: Regular;

+	text-decoration: none;

+	vertical-align: baseline;

+	text-transform: none;

+	font-family:"Courier New";

+}

+

+

+

+

+/* following font face declarations need to be removed for DBCS */

+

+body, h1, h2, h3, h4, h5, h6, p, table, td, caption, th, ul, ol, dl, li, dd, dt {font-family: Arial, Helvetica, sans-serif; color: #000000}

+pre				{ font-family: Courier, monospace}

+

+/* end font face declarations */

+

+/* following font size declarations should be OK for DBCS */

+body, h1, h2, h3, h4, h5, h6, p, table, td, caption, th, ul, ol, dl, li, dd, dt {font-size: 10pt; }

+pre				{ font-size: 10pt}

+

+/* end font size declarations */

+

+body	     { background: #FFFFFF}

+h1           { font-size: 18pt; margin-top: 5; margin-bottom: 1 }	

+h2           { font-size: 14pt; margin-top: 25; margin-bottom: 3 }

+h3           { font-size: 11pt; margin-top: 20; margin-bottom: 3 }

+h4           { font-size: 10pt; margin-top: 20; margin-bottom: 3; font-style: italic }

+p            { margin-top: 10px; margin-bottom: 10px }

+pre	     { margin-left: 6; font-size: 9pt }

+a:link	     { color: #0000FF }

+a:hover	     { color: #000080 }

+a:visited    { text-decoration: underline }

+ul	     { margin-top: 0; margin-bottom: 10 }

+li	     { margin-top: 0; margin-bottom: 0 } 

+li p	     { margin-top: 0; margin-bottom: 0 } 

+ol	     { margin-top: 0; margin-bottom: 10 }

+dl	     { margin-top: 0; margin-bottom: 10 }

+dt	     { margin-top: 0; margin-bottom: 0; font-weight: bold }

+dd	     { margin-top: 0; margin-bottom: 0 }

+strong	     { font-weight: bold}

+em	     { font-style: italic}

+var	     { font-style: italic}

+div.revision { border-left-style: solid; border-left-width: thin; 

+				   border-left-color: #7B68EE; padding-left:5 }

+th	     { font-weight: bold }

diff --git a/bundles/org.eclipse.wst.sse.core/doc/schema.css b/bundles/org.eclipse.wst.sse.core/doc/schema.css
new file mode 100644
index 0000000..4efbf26
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/doc/schema.css
@@ -0,0 +1,66 @@
+H6.CaptionFigColumn#header {

+	font-size:16px; 

+	display:inline

+}

+

+P.Note#copyright {

+	font-size: smaller; 

+	font-style: normal;

+	color: #336699; 

+	display:inline;

+	margin-top: 3.000000pt;

+	margin-bottom: 11.000000pt;

+	margin-right: 0.000000pt;

+	margin-left: 0.000000pt;

+}

+

+P.Code#dtd {

+	color: #800000; 

+	margin-top: 0.000000pt;

+	margin-bottom: 0.000000pt;

+	margin-right: 0.000000pt;

+	margin-left: 10.000000pt;

+}

+

+P.Code#dtdAttlist {

+	color: #800000; 

+	margin-top: 0.000000pt;

+	margin-bottom: 0.000000pt;

+	margin-right: 0.000000pt;

+	margin-left: 20.000000pt;

+}

+

+P.Code#tag {

+	color: #000080; 

+	display:inline;

+	margin-top: 0.000000pt;

+	margin-bottom: 0.000000pt;

+	margin-right: 0.000000pt;

+	margin-left: 0.000000pt;

+}

+

+P.Code#cstring {

+	color: #008000; 

+	display:inline;

+	margin-top: 0.000000pt;

+	margin-bottom: 0.000000pt;

+	margin-right: 0.000000pt;

+	margin-left: 0.000000pt;	

+}

+

+.ConfigMarkup#elementDesc {

+	color: black;

+	margin-top: 0.000000pt;

+	margin-bottom: 0.000000pt;

+	margin-right: 0.000000pt;

+	margin-left: 10.000000pt;

+}

+

+.ConfigMarkup#attlistDesc {

+	color: black;

+	margin-top: 0.000000pt;

+	margin-bottom: 0.000000pt;

+	margin-right: 0.000000pt;

+	margin-left: 32.000000pt;

+}

+

diff --git a/bundles/org.eclipse.wst.sse.core/handyStuff.jpage b/bundles/org.eclipse.wst.sse.core/handyStuff.jpage
new file mode 100644
index 0000000..6447b4e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/handyStuff.jpage
Binary files differ
diff --git a/bundles/org.eclipse.wst.sse.core/plugin.properties b/bundles/org.eclipse.wst.sse.core/plugin.properties
new file mode 100644
index 0000000..1e23274
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/plugin.properties
@@ -0,0 +1,25 @@
+###############################################################################
+# Copyright (c) 2001, 2010 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
+#     Jens Lukowski/Innoopract - initial renaming/restructuring
+#     
+###############################################################################
+providerName=Eclipse Web Tools Platform
+pluginName=Structured Source Model
+# extension names
+Adapt_On_Create_Factory_Extension.name=Adapt On Create Factory Extension
+Document_Types_Extension.name=Document Types Extension
+JSP_Embedded_Content_Type_Handler_Extension.name=JSP Embedded Content Type Handler Extension
+Content_Type_Factory_Contribution_Extension.name=Content Type Factory Contribution Extension
+CSS_Profile_Extension.name=CSS Profile Extension
+Comment_Element_Handler_Extension.name=Comment Element Handler Extension
+Model_Handler_Extension.name=Model Handler Extension
+Format_Processors_Extension_Point.name=Format Processors Extension Point
+Task_Scanner_Extension_Point.name=Task Scanner Extension Point
+Structured_Sources_Task_Extension.name=Detected Task
diff --git a/bundles/org.eclipse.wst.sse.core/plugin.xml b/bundles/org.eclipse.wst.sse.core/plugin.xml
new file mode 100644
index 0000000..1b9d769
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/plugin.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+
+	<!-- deprecated -->
+	<extension-point id="adaptOnCreateFactory" name="%Adapt_On_Create_Factory_Extension.name" schema="schema/adaptOnCreateFactory.exsd"/>
+	<!-- not for use by clients (internal)-->
+	<extension-point id="documentTypes" name="%Document_Types_Extension.name" schema="schema/documentTypes.exsd"/>
+	<!-- not for use by clients (internal)-->
+	<extension-point id="embeddedTypeHandler" name="%JSP_Embedded_Content_Type_Handler_Extension.name" schema="schema/embeddedTypeHandler.exsd"/>
+	<!-- deprecated -->
+	<extension-point id="contentTypeFactoryContribution" name="%Content_Type_Factory_Contribution_Extension.name" schema="schema/contentTypeFactoryContribution.exsd"/>
+	<!-- I commented out ... clients should just use the normal platform way of registering these 
+		adapterFactories. At worst, they'd need a small plugin with 'startup' specified ... but that's 
+		better than us getting hit with the performance impact (of loading plugins and pre-reqs, etc.). 
+		<extension-point id="uriResolverAdapterFactory" name="Resource Adapter Factory for Creating URIResolvers"/>
+	-->
+	<!-- not for use by clients (internal)-->
+	<extension-point id="cssprofile" name="%CSS_Profile_Extension.name" schema="schema/cssprofile.exsd"/>
+	<!-- not for use by clients (internal)-->
+	<extension-point id="commentElementHandler" name="%Comment_Element_Handler_Extension.name" schema="schema/commentElementHandler.exsd"/>
+
+	<!-- not for use by clients (internal)-->
+	<extension-point id="modelHandler" name="%Model_Handler_Extension.name" schema="schema/modelHandler.exsd"/>
+	<!-- not for use by clients (internal)-->
+	<extension-point
+		id="formatProcessors"
+		name="%Format_Processors_Extension_Point.name"
+		schema="schema/formatProcessors.exsd" />
+
+	<!-- not for use by clients (internal)-->
+	<extension-point id="taskscanner" name="%Task_Scanner_Extension_Point.name" schema="schema/taskscanner.exsd"/>
+
+	<!-- Make sure default preference values are set at runtime -->
+	<extension point="org.eclipse.core.runtime.preferences">
+		<initializer
+			class="org.eclipse.wst.sse.core.internal.preferences.PreferenceInitializer" />
+	</extension>
+
+	<extension point="org.eclipse.wst.validation.validatorGroup">
+		<group id="structuredModelGroup">
+			<listener class="org.eclipse.wst.sse.core.internal.validate.ValidatorGroupListener"/>
+		</group>
+	</extension>
+	
+	<!-- Define the StructuredFilePropertyTester as it will handle tracing the entire -->
+	<!-- content type hierarchy for a file. Only operates on IFiles                   -->
+	<!-- Deprecated, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=288216         -->
+	<extension point="org.eclipse.core.expressions.propertyTesters">
+		<propertyTester
+			class="org.eclipse.wst.sse.core.internal.propertytester.StructuredFilePropertyTester"
+			id="org.eclipse.wst.sse.core.expressions.propertyTester.StructuredFilePropertyTester"
+			namespace="org.eclipse.wst.sse.core.resources"
+			properties="contentTypeId"
+			type="org.eclipse.core.resources.IFile">
+    </propertyTester>
+ </extension>
+</plugin>
diff --git a/bundles/org.eclipse.wst.sse.core/schema/adaptOnCreateFactory.exsd b/bundles/org.eclipse.wst.sse.core/schema/adaptOnCreateFactory.exsd
new file mode 100644
index 0000000..ddbf899
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/schema/adaptOnCreateFactory.exsd
@@ -0,0 +1,93 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.sse.core">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.sse.core" id="adaptOnCreateFactory" name="Adapt On Create Factory Extension Point"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is deprecated and should not be used.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2000, 2005 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.sse.core/schema/commentElementHandler.exsd b/bundles/org.eclipse.wst.sse.core/schema/commentElementHandler.exsd
new file mode 100644
index 0000000..633c80c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/schema/commentElementHandler.exsd
@@ -0,0 +1,112 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.sse.core" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appinfo>
+         <meta.schema plugin="org.eclipse.wst.sse.core" id="commentElementHandler" name="Comment Element Handler Extension Point"/>
+      </appinfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appinfo>
+            <meta.element />
+         </appinfo>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="handler-custom"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appinfo>
+                  <meta.attribute translatable="true"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="handler-custom">
+      <complexType>
+         <sequence>
+            <element ref="startwith"/>
+         </sequence>
+         <attribute name="commenttype" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appinfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.wst.xml.core.internal.commentelement.CommentElementHandler"/>
+               </appinfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="startwith">
+      <complexType>
+         <attribute name="prefix" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appinfo>
+         <meta.section type="since"/>
+      </appinfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+
+
+
+   <annotation>
+      <appinfo>
+         <meta.section type="copyright"/>
+      </appinfo>
+      <documentation>
+         Copyright (c) 2005, 2008 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.sse.core/schema/contentTypeFactoryContribution.exsd b/bundles/org.eclipse.wst.sse.core/schema/contentTypeFactoryContribution.exsd
new file mode 100644
index 0000000..cf8418e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/schema/contentTypeFactoryContribution.exsd
@@ -0,0 +1,93 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.sse.core">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.sse.core" id="contentTypeFactoryContribution" name="Content Type Factory Contribution Extension Point"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is deprecated and should not be used.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt; 
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2005 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.sse.core/schema/cssprofile.exsd b/bundles/org.eclipse.wst.sse.core/schema/cssprofile.exsd
new file mode 100644
index 0000000..923e853
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/schema/cssprofile.exsd
@@ -0,0 +1,130 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.sse.core">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.sse.core" id="cssprofile" name="CSS Profile Extension Point"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="profile" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="profile">
+      <complexType>
+         <attribute name="name" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+         <attribute name="default" type="boolean">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="uri" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2005 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.sse.core/schema/documentTypes.exsd b/bundles/org.eclipse.wst.sse.core/schema/documentTypes.exsd
new file mode 100644
index 0000000..b90f35f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/schema/documentTypes.exsd
@@ -0,0 +1,172 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.sse.core">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.sse.core" id="documentTypes" name="Document Types Extension Point"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="documentType" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="documentType">
+      <complexType>
+         <attribute name="elementName" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="displayName" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+         <attribute name="namespaceURI" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="isXHTML" type="boolean">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="hasFrameset" type="boolean">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="publicID" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="systemID" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="defaultXHTML" type="boolean">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="isWML" type="boolean">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="defaultWML" type="boolean">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2005 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.sse.core/schema/embeddedTypeHandler.exsd b/bundles/org.eclipse.wst.sse.core/schema/embeddedTypeHandler.exsd
new file mode 100644
index 0000000..bbcde8d
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/schema/embeddedTypeHandler.exsd
@@ -0,0 +1,109 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.sse.core">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.sse.core" id="embeddedTypeHandler" name="JSP Embedded Content Type Handler Extension Point"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="embeddedTypeHandler"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="embeddedTypeHandler">
+      <complexType>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2005 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.sse.core/schema/formatProcessors.exsd b/bundles/org.eclipse.wst.sse.core/schema/formatProcessors.exsd
new file mode 100644
index 0000000..8ed7304
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/schema/formatProcessors.exsd
@@ -0,0 +1,108 @@
+<?xml version='1.0' encoding='UTF-8'?>

+<!-- Schema file written by PDE -->

+<schema targetNamespace="org.eclipse.wst.sse.core">

+<annotation>

+      <appInfo>

+         <meta.schema plugin="org.eclipse.wst.sse.core" id="formatProcessors" name="Format Processors Extension Point"/>

+      </appInfo>

+      <documentation>

+         &lt;b&gt;This extension point is deprecated and should not be used.&lt;/b&gt;

+      </documentation>

+   </annotation>

+

+   <element name="extension">

+      <complexType>

+         <sequence>

+            <element ref="processor"/>

+         </sequence>

+         <attribute name="point" type="string" use="required">

+            <annotation>

+               <documentation>

+                  a fully qualified identifier of the target extension point

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="id" type="string">

+            <annotation>

+               <documentation>

+                  an optional identifier of the extension instance

+               </documentation>

+            </annotation>

+         </attribute>

+         <attribute name="name" type="string">

+            <annotation>

+               <documentation>

+                  an optional name of the extension instance

+               </documentation>

+               <appInfo>

+                  <meta.attribute translatable="true"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <element name="processor">

+      <complexType>

+         <attribute name="class" type="string" use="required">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+               <appInfo>

+                  <meta.attribute kind="java"/>

+               </appInfo>

+            </annotation>

+         </attribute>

+         <attribute name="contentTypeId" type="string" use="required">

+            <annotation>

+               <documentation>

+                  

+               </documentation>

+            </annotation>

+         </attribute>

+      </complexType>

+   </element>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="since"/>

+      </appInfo>

+      <documentation>

+         &lt;b&gt;This extension point is deprecated and should not be used.&lt;/b&gt;

+      </documentation>

+   </annotation>

+

+   <annotation>

+      <appInfo>

+         <meta.section type="examples"/>

+      </appInfo>

+      <documentation>

+         &lt;pre&gt;

+   &lt;extension

+         point=&quot;org.eclipse.wst.sse.core.formatProcessors&quot;&gt;

+      &lt;processor

+            class=&quot;org.eclipse.wst.sse.core.xml.format.FormatProcessorXML&quot;

+            contentTypeId=&quot;org.eclipse.core.runtime.xml&quot;&gt;

+      &lt;/processor&gt;

+   &lt;/extension&gt;

+&lt;/pre&gt;

+      </documentation>

+   </annotation>

+

+

+

+   <annotation>

+      <appInfo>

+         <meta.section type="copyright"/>

+      </appInfo>

+      <documentation>

+         Copyright (c) 2005, 2007 IBM Corporation and others.&lt;br&gt;

+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 &lt;a

+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;

+      </documentation>

+   </annotation>

+

+</schema>

diff --git a/bundles/org.eclipse.wst.sse.core/schema/modelHandler.exsd b/bundles/org.eclipse.wst.sse.core/schema/modelHandler.exsd
new file mode 100644
index 0000000..ea31dfa
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/schema/modelHandler.exsd
@@ -0,0 +1,114 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.sse.core" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.sse.core" id="modelHandler" name="Model Handler Extension Point"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appInfo>
+            <meta.element />
+         </appInfo>
+      </annotation>
+      <complexType>
+         <sequence minOccurs="0" maxOccurs="unbounded">
+            <element ref="modelHandler"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="modelHandler">
+      <complexType>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="identifier"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.sse.core.internal.ltk.modelhandler.AbstractModelHandler:"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+         <attribute name="associatedContentTypeId" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="default" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+
+
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2005, 2009 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.sse.core/schema/taskscanner.exsd b/bundles/org.eclipse.wst.sse.core/schema/taskscanner.exsd
new file mode 100644
index 0000000..1f80a82
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/schema/taskscanner.exsd
@@ -0,0 +1,104 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.wst.sse.core" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.wst.sse.core" id="taskscanner" name="Task Scanner Extension Point"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <annotation>
+         <appInfo>
+            <meta.element internal="true" />
+         </appInfo>
+      </annotation>
+      <complexType>
+         <sequence>
+            <element ref="scanner"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+               <appInfo>
+                  <meta.attribute translatable="true"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="scanner">
+      <complexType>
+         <attribute name="contentTypeIds" type="string" use="required">
+            <annotation>
+               <documentation>
+                  Content type identifiers for which this scanner applies, separated by commas.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string" use="required">
+            <annotation>
+               <documentation>
+                  Scanner implementation.
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn=":org.eclipse.wst.sse.core.internal.provisional.tasks.IFileTaskScanner"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         &lt;b&gt;This extension point is internal and should not be used by any other plugins.&lt;/b&gt;
+      </documentation>
+   </annotation>
+
+
+
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         Copyright (c) 2005 IBM Corporation and others.&lt;br&gt;
+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 &lt;a
+href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
+      </documentation>
+   </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/AbstractContentSettingsHandler.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/AbstractContentSettingsHandler.java
new file mode 100644
index 0000000..420e3a0
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/AbstractContentSettingsHandler.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+import org.eclipse.core.resources.IResourceDelta;
+
+/**
+ * @deprecated This is package protected so no one cares anyways.
+ */
+abstract class AbstractContentSettingsHandler implements IContentSettingsHandler {
+
+
+	private IContentSettings contentSettings = ContentSettingsCreator.create();
+	private IResourceDelta fDelta;
+
+	private void commonWithRespectToKind() {
+		getContentSettings().releaseCache();
+	}
+
+	protected final IContentSettings getContentSettings() {
+		return contentSettings;
+	}
+
+	protected final IResourceDelta getDelta() {
+		return fDelta;
+	}
+
+
+	/*
+	 * @see IContentSettingsHandler#handle(IResourceDelta)
+	 */
+	public void handle(final IResourceDelta delta) {
+		this.fDelta = delta;
+		// get Resource delta kind
+		final int kind = delta.getKind();
+		// never used!?
+		//IResource resource = delta.getResource();
+
+
+		switch (kind) {
+			case IResourceDelta.CHANGED : {
+				handleChanged();
+			}
+				break;
+			case IResourceDelta.REMOVED : {
+				handleRemoved();
+			}
+				break;
+			case IResourceDelta.ADDED : {
+				handleAdded();
+			}
+				break;
+
+
+		}
+
+
+
+	}
+
+	protected void handleAdded() {
+		commonWithRespectToKind();
+	}
+
+	protected void handleChanged() {
+		commonWithRespectToKind();
+	}
+
+	protected void handleRemoved() {
+		commonWithRespectToKind();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/AbstractSubject.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/AbstractSubject.java
new file mode 100644
index 0000000..fcc98bc
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/AbstractSubject.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @deprecated See
+ *             org.eclipse.html.core.internal.contentproperties.HTMLContentProperties
+ */
+public abstract class AbstractSubject implements INotify, ISubject {
+
+
+
+	private static Map listenerList = new Hashtable();
+
+	public synchronized void addListener(IContentSettingsListener listener) {
+		listenerList.put(listener, listener);
+	}
+
+	/*
+	 * @see IContentSettingsEventSubject#notifyContentSettingsListeners(Object)
+	 */
+	public synchronized void notifyListeners(org.eclipse.core.resources.IResource changedResource) {
+
+		Set keys = listenerList.keySet();
+		Iterator iter = keys.iterator();
+
+		while (iter.hasNext()) {
+			IContentSettingsListener csl = (IContentSettingsListener) iter.next();
+			csl.contentSettingsChanged(changedResource);
+		}
+	}
+
+	public synchronized void removeListener(IContentSettingsListener listener) {
+		listenerList.remove(listener);
+	}
+
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettings.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettings.java
new file mode 100644
index 0000000..8dca387
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettings.java
@@ -0,0 +1,690 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (Intalio) - bug 300443 - some constants aren't static final
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.SSECorePlugin;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * @deprecated See
+ *             org.eclipse.html.core.internal.contentproperties.HTMLContentProperties
+ */
+public class ContentSettings implements IContentSettings {
+	private static final String contentSettingsName = ".contentsettings";//$NON-NLS-1$
+
+	private static SimpleNodeOperator domOperator;
+
+	private static IProject preProject;
+
+	private static final IContentSettings singleton = new ContentSettings();
+
+	public static final String getContentSettingsName() {
+		return contentSettingsName;
+	}
+
+	public synchronized static IContentSettings getInstance() {
+		return singleton;
+	}
+
+	private String contentSettingsPath;
+	private IProject currProject;
+	private static final String fileElementName = "file";//$NON-NLS-1$
+	private static final String PATHATTR = "path"; //$NON-NLS-1$
+	private static final String projectElementName = "project";//$NON-NLS-1$
+
+
+
+	private static final String rootElementName = "contentsettings";//$NON-NLS-1$
+
+
+
+	private ContentSettings() {
+		currProject = null;
+		contentSettingsPath = null;
+	}
+
+
+	private void _setProperties(final IResource resource, final Map properties) {
+		if (resource == null || properties == null || properties.isEmpty())
+			return;
+		if (!(resource.getType() == IResource.PROJECT || resource.getType() == IResource.FILE))
+			return;
+
+		contentSettingsPath = getContentSettingsPath(resource);
+		if (contentSettingsPath == null)
+			return;
+
+		try {
+
+			if (!existsContentSettings()) {
+				// create DOM tree for new XML Document
+				createNewDOMTree();
+			}
+			else {
+				// create DOM tree from existing contentsettings.
+				createDOMTree();
+			}
+
+		}
+		catch (SimpleNodeOperator.ReadContentSettingsFailureException e) {
+			Logger.logException(e);
+			try {
+				createNewDOMTree();
+				writeDOMDocument();
+			}
+			catch (SimpleNodeOperator.CreateContentSettingsFailureException e2) {
+				Logger.logException(e2);
+				preProject = currProject;
+				return;
+			}
+			catch (SimpleNodeOperator.WriteContentSettingsFailureException e2) {
+				Logger.logException(e2);
+				preProject = currProject;
+				return;
+			}
+
+		}
+		catch (SimpleNodeOperator.CreateContentSettingsFailureException e) {
+			Logger.logException(e);
+			preProject = currProject;
+			return;
+		}
+
+		Element e = null;
+		if (resource.getType() == IResource.PROJECT) {
+			e = (Element) domOperator.getElementWithNodeName(projectElementName);
+			if (e == null) {
+				// create project Element and add it into tree
+				e = (Element) domOperator.addElementUnderRoot(projectElementName);
+			}
+		}
+		else if (resource.getType() == IResource.FILE) {
+			// check exists file Element
+			e = (Element) domOperator.getElementWithAttribute(getPathAttr(), getRelativePathFromProject(resource));
+			if (e == null) {
+				// create file Element and add path into it.
+				e = (Element) domOperator.addElementUnderRoot(fileElementName);
+				domOperator.addAttributeAt(e, getPathAttr(), getRelativePathFromProject(resource));
+			}
+		}
+
+		// check exists propertyName attribute
+		Map attrList = domOperator.getAttributesOf(e);
+		boolean hasAttr = true;
+		if (attrList == null || attrList.isEmpty())
+			hasAttr = false;
+		Set keys = properties.keySet();
+		Iterator ii = keys.iterator();
+		while (ii.hasNext()) {
+			String propertyName = (String) ii.next();
+			String propertyValue = (String) properties.get(propertyName);
+
+
+			if (!hasAttr || (String) attrList.get(propertyName) == null)
+				// create propertyName attribute and add
+				domOperator.addAttributeAt(e, propertyName, propertyValue);
+			else
+				// set attribute value
+				domOperator.updateAttributeAt(e, propertyName, propertyValue);
+		}
+
+		// write dom tree into .contentsettings
+		try {
+			writeDOMDocument();
+		}
+		catch (SimpleNodeOperator.WriteContentSettingsFailureException ex) {
+			Logger.logException(ex);
+			preProject = currProject;
+			return;
+		}
+
+		preProject = currProject;
+
+
+	}
+
+
+	private void _setProperty(final IResource resource, final String propertyName, final String propertyValue) {
+		if (resource == null || propertyName == null)
+			return;
+		if (!(resource.getType() == IResource.PROJECT || resource.getType() == IResource.FILE))
+			return;
+
+		contentSettingsPath = getContentSettingsPath(resource);
+		if (contentSettingsPath == null)
+			return;
+
+		try {
+
+			if (!existsContentSettings()) {
+				// create DOM tree for new XML Document
+				createNewDOMTree();
+			}
+			else {
+				// create DOM tree from existing contentsettings.
+				createDOMTree();
+			}
+
+		}
+		catch (SimpleNodeOperator.ReadContentSettingsFailureException e) {
+			Logger.logException(e);
+			try {
+				createNewDOMTree();
+				writeDOMDocument();
+			}
+			catch (SimpleNodeOperator.CreateContentSettingsFailureException e2) {
+				Logger.logException(e2);
+				preProject = currProject;
+				return;
+			}
+			catch (SimpleNodeOperator.WriteContentSettingsFailureException e2) {
+				Logger.logException(e2);
+				preProject = currProject;
+				return;
+			}
+
+		}
+		catch (SimpleNodeOperator.CreateContentSettingsFailureException e) {
+			Logger.logException(e);
+			preProject = currProject;
+			return;
+		}
+
+		Element e = null;
+		if (resource.getType() == IResource.PROJECT) {
+			e = (Element) domOperator.getElementWithNodeName(projectElementName);
+			if (e == null) {
+				// create project Element and add it into tree
+				e = (Element) domOperator.addElementUnderRoot(projectElementName);
+			}
+		}
+		else if (resource.getType() == IResource.FILE) {
+			// check exists file Element
+			e = (Element) domOperator.getElementWithAttribute(getPathAttr(), getRelativePathFromProject(resource));
+			if (e == null) {
+				// create file Element and add path into it.
+				e = (Element) domOperator.addElementUnderRoot(fileElementName);
+				domOperator.addAttributeAt(e, getPathAttr(), getRelativePathFromProject(resource));
+			}
+		}
+
+		// check exists propertyName attribute
+
+		Map attrList = domOperator.getAttributesOf(e);
+		if (attrList == null || attrList.isEmpty() || (String) attrList.get(propertyName) == null)
+			// create propertyName attribute and add
+			domOperator.addAttributeAt(e, propertyName, propertyValue);
+		else
+			// set attribute value
+			domOperator.updateAttributeAt(e, propertyName, propertyValue);
+
+
+		// write dom tree into .contentsettings
+		try {
+			writeDOMDocument();
+		}
+		catch (SimpleNodeOperator.WriteContentSettingsFailureException ex) {
+			Logger.logException(ex);
+			preProject = currProject;
+			return;
+		}
+
+		preProject = currProject;
+
+
+	}
+
+
+	private void createDOMTree() throws SimpleNodeOperator.ReadContentSettingsFailureException {
+		if (domOperator == null || (currProject != null && (!currProject.equals(preProject)) && contentSettingsPath != null))
+			domOperator = new SimpleNodeOperator(contentSettingsPath);
+
+
+	}
+
+	/*
+	 * private void createNewDOMTree() throws
+	 * SimpleNodeOperator.CreateContentSettingsFailureException{ // create New
+	 * document when no file exists. DOMImplementation impl =
+	 * DOMImplementationImpl.getDOMImplementation(); Document document =
+	 * impl.createDocument(null,rootElementName,null); domOperator = new
+	 * SimpleNodeOperator(document); }
+	 */
+	private void createNewDOMTree() throws SimpleNodeOperator.CreateContentSettingsFailureException {
+		Document document = null;
+		try {
+			document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+		}
+		catch (ParserConfigurationException e) {
+			Logger.logException("exception creating document", e); //$NON-NLS-1$
+		}
+		catch (FactoryConfigurationError e) {
+			Logger.logException("exception creating document", e); //$NON-NLS-1$
+		}
+		if (document != null) {
+			document.appendChild(document.createElement(rootElementName));
+			domOperator = new SimpleNodeOperator(document);
+		}
+	}
+
+
+	/**
+	 * 
+	 */
+	public synchronized void deleteAllProperties(final IResource deletedFile) {
+		if (deletedFile == null)
+			return;
+		// if (deletedFile.exists()) return;
+		if ((deletedFile).getType() != IResource.FILE && (deletedFile).getType() != IResource.PROJECT)
+			return;
+
+
+		contentSettingsPath = getContentSettingsPath(deletedFile);// getProjectOf((IResource)deletedFile)
+		// +
+		// IPath.SEPARATOR
+		// +
+		// contentSettingsName;
+		if (contentSettingsPath == null)
+			return;
+		if (!existsContentSettings())
+			return;
+
+		try {
+			createDOMTree();
+		}
+		catch (SimpleNodeOperator.ReadContentSettingsFailureException e) {
+			Logger.logException(e);
+			return;
+		}
+
+		Element e = null;
+		if (deletedFile.getType() == IResource.PROJECT)
+			// select project element and get attribute
+			e = (Element) domOperator.getElementWithNodeName(projectElementName);
+		else if (deletedFile.getType() == IResource.FILE)
+			e = (Element) domOperator.getElementWithAttribute(getPathAttr(), getRelativePathFromProject(deletedFile));
+		if (e == null) {
+			preProject = currProject;
+			return;
+		}
+
+
+		// when deletedFile entry exists.
+		if (deletedFile.getType() == IResource.PROJECT)
+			domOperator.removeElementWith(projectElementName);
+		else if (deletedFile.getType() == IResource.FILE)
+			domOperator.removeElementWith(getPathAttr(), getRelativePathFromProject(deletedFile));
+
+
+		// write dom tree into .contentsettings
+		try {
+			writeDOMDocument();
+		}
+		catch (SimpleNodeOperator.WriteContentSettingsFailureException ex) {
+			Logger.logException(ex);
+			preProject = currProject;
+			return;
+		}
+
+		preProject = currProject;
+
+
+	}
+
+	public synchronized void deleteProperty(final IResource resource, final String propertyName) {
+		if (resource == null)
+			return;
+		if (!(resource.getType() == IResource.PROJECT || resource.getType() == IResource.FILE))
+			return;
+		contentSettingsPath = getContentSettingsPath(resource);
+		if (contentSettingsPath == null)
+			return;
+
+		if (!existsContentSettings()) {
+			return; // when .contentsettings.xml is NOT exist.
+		}
+		try {
+			createDOMTree();
+		}
+		catch (SimpleNodeOperator.ReadContentSettingsFailureException e) {
+			Logger.logException(e);
+			try {
+				createNewDOMTree();
+				writeDOMDocument();
+			}
+			catch (SimpleNodeOperator.CreateContentSettingsFailureException e2) {
+				Logger.logException(e2);
+				preProject = currProject;
+				return;
+			}
+			catch (SimpleNodeOperator.WriteContentSettingsFailureException e2) {
+				Logger.logException(e2);
+				preProject = currProject;
+				return;
+			}
+		}
+
+		Element e = null;
+		if (resource.getType() == IResource.PROJECT)
+			// select project element and get attribute
+			e = (Element) domOperator.getElementWithNodeName(projectElementName);
+		else if (resource.getType() == IResource.FILE)
+			e = (Element) domOperator.getElementWithAttribute(getPathAttr(), getRelativePathFromProject(resource));
+
+
+		if (e != null) {
+			domOperator.removeAttributeAt(e, propertyName);
+			// write dom tree into .contentsettings
+			try {
+				writeDOMDocument();
+			}
+			catch (SimpleNodeOperator.WriteContentSettingsFailureException ex) {
+				Logger.logException(ex);
+				preProject = currProject;
+				return;
+			}
+		}
+
+		preProject = currProject;
+
+	}
+
+
+	private boolean existsContentSettings() {
+		if (contentSettingsPath == null)
+			return false;
+
+		IResource file = currProject.getFile(contentSettingsName);
+		if (file == null)
+			return false;
+		if (file.isAccessible())
+			return true;
+		else
+			return false;
+
+	}
+
+	public boolean existsProperties(IResource resource) {
+		if (resource == null)
+			return false;
+
+		if (!(resource.getType() == IResource.PROJECT || resource.getType() == IResource.FILE))
+			return false;
+
+		contentSettingsPath = getContentSettingsPath(resource);
+		if (contentSettingsPath == null)
+			return false;
+
+		if (!existsContentSettings())
+			return false; // when .contentsettings.xml is NOT exist.
+
+		try {
+			createDOMTree();
+		}
+		catch (SimpleNodeOperator.ReadContentSettingsFailureException e1) {
+			return false;
+		}
+
+		Element e = null;
+		if (resource.getType() == IResource.PROJECT)
+			// select project element and get attribute
+			e = (Element) domOperator.getElementWithNodeName(projectElementName);
+		else if (resource.getType() == IResource.FILE)
+			e = (Element) domOperator.getElementWithAttribute(getPathAttr(), getRelativePathFromProject(resource));
+
+		preProject = currProject;
+		if (e == null)
+			return false;
+
+		Map properties = domOperator.getAttributesOf(e);
+		if (properties == null)
+			return false;
+		properties.remove(getPathAttr());// if IFile,removed
+		if (properties.isEmpty())
+			return false;
+		return true;
+
+	}
+
+	private String getContentSettingsPath(IResource resource) {
+		IProject project = null;
+		if (resource.getType() == IResource.PROJECT)
+			project = (IProject) resource;
+		else
+			project = resource.getProject();
+
+		IPath projectLocation = project.getLocation();
+		if (projectLocation == null) {
+			/**
+			 * As a deprecated class, perfect operation in new scenarios such
+			 * as with EFS is not promised.
+			 */
+			return SSECorePlugin.getDefault().getStateLocation().append(rootElementName).append(project.getName()).toString();
+		}
+
+		return projectLocation.addTrailingSeparator().append(contentSettingsName).toString();
+	}
+
+	public final String getPathAttr() {
+		return PATHATTR;
+	}
+
+	public synchronized Map getProperties(final IResource resource) {
+		if (resource == null)
+			return null;
+
+		if (!(resource.getType() == IResource.PROJECT || resource.getType() == IResource.FILE))
+			return null;
+
+		contentSettingsPath = getContentSettingsPath(resource);
+		if (contentSettingsPath == null)
+			return null;
+
+		if (!existsContentSettings()) {
+			return null; // when .contentsettings.xml is NOT exist.
+		}
+
+
+		try {
+			createDOMTree();
+		}
+		catch (SimpleNodeOperator.ReadContentSettingsFailureException e1) {
+			Logger.logException(e1);
+			// create DOM tree for new XML Document
+			try {
+				createNewDOMTree();
+				writeDOMDocument();
+			}
+			catch (SimpleNodeOperator.CreateContentSettingsFailureException e2) {
+				Logger.logException(e2);
+				preProject = currProject;
+				return null;
+			}
+			catch (SimpleNodeOperator.WriteContentSettingsFailureException e2) {
+				Logger.logException(e2);
+				preProject = currProject;
+				return null;
+			}
+
+		}
+
+
+		Element e = null;
+		if (resource.getType() == IResource.PROJECT)
+			// select project element and get attribute
+			e = (Element) domOperator.getElementWithNodeName(projectElementName);
+		else if (resource.getType() == IResource.FILE)
+			e = (Element) domOperator.getElementWithAttribute(getPathAttr(), getRelativePathFromProject(resource));
+
+
+		if (e != null) {
+
+			Map properties = domOperator.getAttributesOf(e);
+			preProject = currProject;
+			if (properties == null)
+				return null;
+			if (properties.isEmpty())
+				return null;
+			properties.remove(getPathAttr());
+			return properties;
+		}
+		else {
+			preProject = currProject;
+			return null;// when project or file element is NOT exist.
+		}
+	}
+
+	public synchronized String getProperty(final IResource resource, final String propertyName) {
+		if (resource == null)
+			return null;
+
+		if (!(resource.getType() == IResource.PROJECT || resource.getType() == IResource.FILE))
+			return null;
+
+		contentSettingsPath = getContentSettingsPath(resource);
+		if (contentSettingsPath == null)
+			return null;
+
+		if (!existsContentSettings()) {
+			return null; // when .contentsettings.xml is NOT exist.
+		}
+
+
+		try {
+			createDOMTree();
+		}
+		catch (SimpleNodeOperator.ReadContentSettingsFailureException e1) {
+			Logger.logException(e1);
+			// create DOM tree for new XML Document
+			try {
+				createNewDOMTree();
+				writeDOMDocument();
+			}
+			catch (SimpleNodeOperator.CreateContentSettingsFailureException e2) {
+				Logger.logException(e2);
+				preProject = currProject;
+				return null;
+			}
+			catch (SimpleNodeOperator.WriteContentSettingsFailureException e2) {
+				Logger.logException(e2);
+				preProject = currProject;
+				return null;
+			}
+
+		}
+
+
+		Element e = null;
+		if (resource.getType() == IResource.PROJECT)
+			// select project element and get attribute
+			e = (Element) domOperator.getElementWithNodeName(projectElementName);
+		else if (resource.getType() == IResource.FILE)
+			e = (Element) domOperator.getElementWithAttribute(getPathAttr(), getRelativePathFromProject(resource));
+
+
+		if (e != null) {
+			String result = e.getAttribute(propertyName);
+			preProject = currProject;
+			return result;
+		}
+		else {
+			preProject = currProject;
+			return null;// when project or file element is NOT exist.
+		}
+	}
+
+	private String getRelativePathFromProject(IResource resource) {
+		if (resource == null)
+			return null;
+
+		IPath path = resource.getProjectRelativePath();
+		if (path == null)
+			return null; // if resource is project or workspace root
+		String resourcePath = path.toString();
+
+		return resourcePath;
+
+	}
+
+	public synchronized void releaseCache() {
+		domOperator = null;
+	}
+
+	public synchronized void setProperties(final IResource resource, final Map properties) {
+		// deny to set "path" attribute value.
+		Set keys = properties.keySet();
+		Iterator ii = keys.iterator();
+		while (ii.hasNext()) {
+			if (this.getPathAttr().equals(ii.next()))
+				return;
+		}
+		this._setProperties(resource, properties);
+	}
+
+	public synchronized void setProperty(final IResource resource, final String propertyName, final String propertyValue) {
+		// deny to set "path" attribute value.
+		if (this.getPathAttr().equals(propertyName))
+			return;
+		this._setProperty(resource, propertyName, propertyValue);
+	}
+
+	private void writeDOMDocument() throws SimpleNodeOperator.WriteContentSettingsFailureException {
+		try {
+
+			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+			domOperator.writeDocument(outputStream);
+			outputStream.flush();
+			outputStream.close();
+
+			ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
+
+			IFile outputFile = currProject.getFile(contentSettingsName);
+			if (outputFile.exists())
+				outputFile.setContents(inputStream, true, true, null);
+			else
+				outputFile.create(inputStream, true, null);
+
+			inputStream.close();
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+			throw new SimpleNodeOperator.WriteContentSettingsFailureException("invalid outputFile in writeDOMDocument()");//$NON-NLS-1$
+		}
+		catch (IOException e) {
+			Logger.logException(e);
+			throw new SimpleNodeOperator.WriteContentSettingsFailureException("invalid outputStream or inputStream in writeDOMDocument()");//$NON-NLS-1$
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsChangeSubject.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsChangeSubject.java
new file mode 100644
index 0000000..7bc580b
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsChangeSubject.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+
+/**
+ * @deprecated See
+ *             org.eclipse.html.core.internal.contentproperties.HTMLContentProperties
+ */
+public class ContentSettingsChangeSubject extends AbstractSubject {
+
+
+	private static INotify notify;
+	private static ISubject subject;
+
+	protected static INotify getNotify() {
+		if (notify == null && subject == null) {
+			synchronized (ContentSettingsChangeSubject.class) {
+				if (notify == null && subject == null) {
+					notify = new ContentSettingsChangeSubject();
+					subject = (ISubject) notify;
+				}
+			}
+		}
+
+		return notify;
+	}
+
+	public static ISubject getSubject() {
+		if (subject == null && notify == null) {
+			synchronized (ContentSettingsChangeSubject.class) {
+				if (subject == null && notify == null) {
+					subject = new ContentSettingsChangeSubject();
+					notify = (INotify) subject;
+				}
+			}
+		}
+		return subject;
+	}
+
+	public synchronized void addListener(IContentSettingsListener listener) {
+		super.addListener(listener);
+	}
+
+	public synchronized void notifyListeners(org.eclipse.core.resources.IResource changedResource) {
+		super.notifyListeners(changedResource);
+	}
+
+	public synchronized void removeListener(IContentSettingsListener listener) {
+		super.removeListener(listener);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsCreator.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsCreator.java
new file mode 100644
index 0000000..9dd355c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsCreator.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+
+/**
+ * @deprecated See
+ *             org.eclipse.html.core.internal.contentproperties.HTMLContentProperties
+ */
+public class ContentSettingsCreator {
+
+	public final static IContentSettings create() {
+		return ContentSettings.getInstance();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsFileHandler.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsFileHandler.java
new file mode 100644
index 0000000..0c52604
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsFileHandler.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+
+
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+
+/**
+* @deprecated This is package protected so no one cares anyways.
+*/
+class ContentSettingsFileHandler extends AbstractContentSettingsHandler {
+
+
+
+	private Map properties;
+
+
+	private void getProperties(IResource file) {
+		properties = getContentSettings().getProperties(file);
+	}
+
+	/*
+	 * @see AbstractContentSettingsHandler#handleAdded()
+	 */
+	protected void handleAdded() {
+		super.handleAdded();
+
+		if (super.getDelta().getFlags() == 0) {
+			// pulldown memu->copy->create file without override, new file,
+			// import without override
+			// copy,new,import has same kind(=1) and flag(=0).
+
+		} else if ((getDelta().getFlags() & IResourceDelta.MOVED_FROM) != 0) {
+			// pulldown menu-> rename without override,pulldown menu->move
+			// without override
+			// instead of this method,handleRemoved() works for this delta
+
+		}
+
+	}
+
+
+	/*
+	 * @see AbstractContentSettingsHandler#handleChanged()
+	 */
+	protected void handleChanged() {
+		// edit
+		if (getDelta().getFlags() == IResourceDelta.CONTENT && (getDelta().getFlags() & IResourceDelta.REPLACED) == 0) {
+			super.handleChanged();
+
+		} else if (getDelta().getFlags() == IResourceDelta.CONTENT && (getDelta().getFlags() & IResourceDelta.REPLACED) != 0) {
+			// override as a result of copy or import
+			// in Web project, copy with override doesn't happen
+
+			// override as move or rename
+			// handleRemoved() works for this delta
+			super.handleChanged();
+
+		}
+
+
+	}
+
+	/*
+	 * @see AbstractContentSettingsHandler#handleRemoved()
+	 */
+	protected void handleRemoved() {
+		super.handleRemoved();
+		IFile deletedFile = null;
+
+		// if entry exists then remove it.
+		if (getDelta().getFlags() == 0) {
+			// pulldown menu->delete
+			deletedFile = (IFile) getDelta().getResource();
+
+			if (deletedFile == null)
+				return;
+			getContentSettings().deleteAllProperties(deletedFile);
+
+			getContentSettings().releaseCache();
+		}
+
+		else if ((getDelta().getFlags() & IResourceDelta.MOVED_TO) != 0) {
+
+			// pulldown menu-> rename, pulldown menu->move
+			deletedFile = (IFile) getDelta().getResource();
+			getProperties(deletedFile);
+
+			// get destination IResource
+			IPath targetPath = getDelta().getMovedToPath();
+			IWorkspaceRoot iwr = ResourcesPlugin.getWorkspace().getRoot();
+			IResource targetFile = iwr.getFile(targetPath);//iwr.findMember(targetPath);
+
+			// set property of destination file
+			getContentSettings().deleteAllProperties(targetFile);
+			setProperties(targetFile);
+			if (properties != null)
+				properties.clear();
+			properties = null;
+		}
+
+		if (deletedFile == null)
+			return;
+		getContentSettings().deleteAllProperties(deletedFile);
+
+		getContentSettings().releaseCache();
+
+	}
+
+	private void setProperties(IResource file) {
+		if (file.getFileExtension() == null)
+			return;
+		if (!(file.getFileExtension().equalsIgnoreCase("shtml")//$NON-NLS-1$
+					|| file.getFileExtension().equalsIgnoreCase("htm")//$NON-NLS-1$
+					|| file.getFileExtension().equalsIgnoreCase("html")//$NON-NLS-1$
+					|| file.getFileExtension().equalsIgnoreCase("jhtml")//$NON-NLS-1$
+					|| file.getFileExtension().equalsIgnoreCase("xhtml")//$NON-NLS-1$
+					|| file.getFileExtension().equalsIgnoreCase("jsp")//$NON-NLS-1$
+					|| file.getFileExtension().equalsIgnoreCase("css")//$NON-NLS-1$
+					|| file.getFileExtension().equalsIgnoreCase("jsf")//$NON-NLS-1$
+		|| file.getFileExtension().equalsIgnoreCase("jspf")))//$NON-NLS-1$
+			return;
+		if (properties == null || properties.isEmpty())
+			return;
+		getContentSettings().setProperties(file, properties);
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsSelfHandler.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsSelfHandler.java
new file mode 100644
index 0000000..27aa2b8
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsSelfHandler.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+
+
+import org.eclipse.core.resources.IResourceDelta;
+
+/**
+* @deprecated This is package protected so no one cares anyways.
+*/
+final class ContentSettingsSelfHandler extends AbstractContentSettingsHandler {
+
+	private static INotify notify;// = new ContentSettingsChangedSubject();
+
+
+	private final void getSubject() {
+		notify = ContentSettingsChangeSubject.getNotify();
+	}
+
+	/*
+	 * @see AbstractContentSettingsHandler#handleAdded()
+	 */
+	protected void handleAdded() {
+		getSubject();
+		if (super.getDelta().getFlags() == 0) {
+			// pulldown memu->copy->create file without override, new file,
+			// property page create .contentsettings
+			super.handleAdded();
+			notify.notifyListeners(getDelta().getResource());
+
+		} else if ((getDelta().getFlags() & IResourceDelta.MOVED_FROM) != 0) {
+			// pulldown menu-> rename without override,pulldown menu->move
+			// without override
+			super.handleAdded();
+			notify.notifyListeners(getDelta().getResource());
+
+		}
+
+	}
+
+
+	/*
+	 * @see AbstractContentSettingsHandler#handleChanged()
+	 */
+	protected void handleChanged() {
+		getSubject();
+		if ((getDelta().getFlags() & IResourceDelta.CONTENT) != 0 && (getDelta().getFlags() & IResourceDelta.REPLACED) == 0) {
+			// result of edit, property page operate setProperty(apply or ok
+			// button) in .contentsettings
+			super.handleChanged();
+
+			notify.notifyListeners(getDelta().getResource());
+
+		} else if ((getDelta().getFlags() & IResourceDelta.CONTENT) != 0 && (getDelta().getFlags() & IResourceDelta.REPLACED) != 0) {
+			super.handleChanged();
+			notify.notifyListeners(getDelta().getResource());
+
+		}
+
+
+	}
+
+	/*
+	 * @see AbstractContentSettingsHandler#handleRemoved()
+	 */
+	protected void handleRemoved() {
+		getSubject();
+		if (getDelta().getFlags() == 0) {
+			// pulldown menu->delete
+			super.handleRemoved();
+			notify.notifyListeners(getDelta().getResource());
+
+		} else if ((getDelta().getFlags() & IResourceDelta.MOVED_TO) != 0) {
+			// pulldown menu-> rename, pulldown menu->move
+			super.handleRemoved();
+			notify.notifyListeners(getDelta().getResource());
+
+		}
+
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsSynchronizer.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsSynchronizer.java
new file mode 100644
index 0000000..e698b65
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ContentSettingsSynchronizer.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (Intalio) - bug 300434 - Make inner classes static where possible
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.wst.sse.core.internal.Logger;
+
+/**
+ * @deprecated See
+ *             org.eclipse.html.core.internal.contentproperties.HTMLContentProperties
+ */
+public class ContentSettingsSynchronizer implements IResourceChangeListener {
+	static class ContentSettingsVisitor implements IResourceDeltaVisitor {
+		// redefinition in ContentSettings.java
+		private String contentSettingsName = ContentSettings.getContentSettingsName(); //$NON-NLS-1$
+		private IResourceChangeEvent fEvent;
+		private IContentSettingsHandler handler;
+
+		public ContentSettingsVisitor(IResourceChangeEvent event) {
+			this.fEvent = event;
+		}
+
+		/**
+		 * @see IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
+		 */
+		public boolean visit(IResourceDelta delta) {
+			if (delta == null)
+				return false;
+			IResource resource = delta.getResource();
+			if (resource == null)
+				return false;
+			// parent folder or project
+			if (delta.getKind() == IResourceDelta.CHANGED && delta.getFlags() == 0)
+				return true;
+			final int resourceType = resource.getType();
+			switch (resourceType) {
+				case IResource.PROJECT :
+					return false;
+				case IResource.FILE :
+					// whether resource is .contentsettings file or not
+					IProject project = delta.getResource().getProject();
+					if (this.fEvent.getType() == IResourceChangeEvent.POST_CHANGE && resource.equals(project.getFile(this.contentSettingsName))) {
+						// new object for .contentsettings
+						handler = new ContentSettingsSelfHandler();
+					}
+					else if (this.fEvent.getType() == IResourceChangeEvent.PRE_BUILD && resource.getFileExtension() != null) {
+						// TODO change to content type!
+						if (resource.getFileExtension().equalsIgnoreCase("shtml") //$NON-NLS-1$
+									|| resource.getFileExtension().equalsIgnoreCase("htm") //$NON-NLS-1$
+									|| resource.getFileExtension().equalsIgnoreCase("html") //$NON-NLS-1$
+									|| resource.getFileExtension().equalsIgnoreCase("jhtml") //$NON-NLS-1$
+									|| resource.getFileExtension().equalsIgnoreCase("xhtml") //$NON-NLS-1$
+									|| resource.getFileExtension().equalsIgnoreCase("jsp") //$NON-NLS-1$
+									|| resource.getFileExtension().equalsIgnoreCase("css") //$NON-NLS-1$
+									|| resource.getFileExtension().equalsIgnoreCase("jsf") //$NON-NLS-1$
+									|| resource.getFileExtension().equalsIgnoreCase("jspf")) { //$NON-NLS-1$
+							// new object for IFile
+							handler = new ContentSettingsFileHandler();
+							handler.handle(delta);
+							handler = null;
+							return true;
+						}
+					}
+					else
+						return false; // true or false;motomoto true;
+					break;
+				case IResource.FOLDER :
+					return true;
+				default :
+					return true;
+			}
+//			final IResourceDelta fDelta = delta;
+//			final IContentSettingsHandler deltaHandler = this.handler;
+			// XXX FIXME
+			// I commented out following to move this to "model" 
+			// packages. Since wasnt't hooked up/working anyway, I think 
+			// ok for now, but need to re-work as Job, once we do implement 
+			// settings for resources again. 
+//			Display display = getDisplay();
+//			if (display != null && !display.isDisposed()) {
+//				display.asyncExec(new Runnable() {
+//					public void run() {
+//						if (deltaHandler != null) {
+//							deltaHandler.handle(fDelta);
+//						}
+//					}
+//				});
+//			}
+//			else if (deltaHandler != null) {
+//				deltaHandler.handle(fDelta);
+//			}
+			handler = null;
+			return true; // true or false;motomoto true;
+		}
+	}
+
+	private static ContentSettingsSynchronizer instance = null;
+
+	public synchronized static ContentSettingsSynchronizer getInstance() {
+		if (instance == null)
+			instance = new ContentSettingsSynchronizer();
+		return instance;
+	}
+
+	private ContentSettingsVisitor csVisitor;
+	private boolean fListening = false;
+	private IProject fProject;
+
+
+	private final IProject getProject() {
+		return fProject;
+	}
+
+	private final IWorkspace getWorkspace() {
+		if (getProject() == null)
+			return ResourcesPlugin.getWorkspace();
+		return getProject().getWorkspace();
+	}
+
+	public synchronized void install() {
+		if (!fListening) {
+			getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.PRE_BUILD | IResourceChangeEvent.POST_CHANGE);
+			fListening = true;
+		}
+	}
+
+	/**
+	 * @return
+	 */
+	public synchronized boolean isListening() {
+		return fListening;
+	}
+
+	/*
+	 * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent)
+	 */
+	public void resourceChanged(IResourceChangeEvent event) {
+		IResourceDelta delta = event.getDelta();
+		if (delta != null) {
+			try {
+				if (csVisitor == null)
+					csVisitor = new ContentSettingsVisitor(event);
+				delta.accept(csVisitor);
+			}
+			catch (CoreException e) {
+				Logger.logException(e);
+			}
+		}
+		csVisitor = null;
+	}
+
+	public synchronized void unInstall() {
+		getWorkspace().removeResourceChangeListener(this);
+		fListening = false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/IContentSettings.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/IContentSettings.java
new file mode 100644
index 0000000..058dd5c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/IContentSettings.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+
+
+import java.util.Map;
+
+import org.eclipse.core.resources.IResource;
+
+/**
+ * @deprecated See
+ *             org.eclipse.html.core.internal.contentproperties.HTMLContentProperties
+ */
+public interface IContentSettings {
+	/**
+	 * 
+	 */
+	public final String CSS_PROFILE = "css-profile"; //$NON-NLS-1$
+	/**
+	 * 
+	 */
+	public final String DEVICE_PROFILE = "target-device"; //$NON-NLS-1$
+
+	/**
+	 * 
+	 */
+	public final String DOCUMENT_TYPE = "document-type"; //$NON-NLS-1$
+	/**
+	 * 
+	 */
+	public final String HTML_DOCUMENT_TYPE = "html-document-type"; //$NON-NLS-1$
+
+	/**
+	 * 
+	 */
+	public void deleteAllProperties(final IResource deletedFile);
+
+	/**
+	 * 
+	 */
+	public void deleteProperty(final IResource resource, final String propertyName);
+
+	/**
+	 * 
+	 */
+	public boolean existsProperties(IResource resource);
+
+	/**
+	 * 
+	 */
+	public Map getProperties(final IResource resource);
+
+	/**
+	 * 
+	 */
+	public String getProperty(final IResource resource, final String propertyName);
+
+	/**
+	 * release cache of DOM tree in .contentsettings
+	 */
+	public void releaseCache();
+
+	/**
+	 * 
+	 */
+	public void setProperties(final IResource resource, final Map properties);
+
+	/**
+	 * 
+	 */
+	public void setProperty(final IResource resource, final String propertyName, final String propertyValue);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/IContentSettingsHandler.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/IContentSettingsHandler.java
new file mode 100644
index 0000000..8ef8b45
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/IContentSettingsHandler.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+
+
+import org.eclipse.core.resources.IResourceDelta;
+
+/**
+* @deprecated This is package protected so no one cares anyways.
+*/
+interface IContentSettingsHandler {
+
+	public void handle(final IResourceDelta delta);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/IContentSettingsListener.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/IContentSettingsListener.java
new file mode 100644
index 0000000..41151f8
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/IContentSettingsListener.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+/**
+ * @deprecated See
+ *             org.eclipse.html.core.internal.contentproperties.HTMLContentProperties
+ */
+public interface IContentSettingsListener {
+
+	void contentSettingsChanged(org.eclipse.core.resources.IResource e);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/INotify.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/INotify.java
new file mode 100644
index 0000000..4dcf5fe
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/INotify.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+
+/**
+* @deprecated This is package protected so no one cares anyways.
+*/
+interface INotify {
+
+	void notifyListeners(org.eclipse.core.resources.IResource resource);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ISubject.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ISubject.java
new file mode 100644
index 0000000..4ff4030
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/ISubject.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+
+/**
+ * @deprecated See
+ *             org.eclipse.html.core.internal.contentproperties.HTMLContentProperties
+ */
+public interface ISubject {
+
+	void addListener(IContentSettingsListener listener);
+
+	void removeListener(IContentSettingsListener listener);
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/SimpleNodeOperator.java b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/SimpleNodeOperator.java
new file mode 100644
index 0000000..ace7a38
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-contentproperties/org/eclipse/wst/sse/internal/contentproperties/SimpleNodeOperator.java
@@ -0,0 +1,354 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (Intalio) - bug 300434 - Make inner classes static where possible
+ *******************************************************************************/
+package org.eclipse.wst.sse.internal.contentproperties;
+
+
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.traversal.NodeIterator;
+import org.xml.sax.SAXException;
+
+/**
+* @deprecated This is package protected so no one cares anyways.
+*/
+class SimpleNodeOperator {
+
+	static class CreateContentSettingsFailureException extends Exception {
+		/**
+		 * Comment for <code>serialVersionUID</code>
+		 */
+		private static final long serialVersionUID = 1L;
+
+		public CreateContentSettingsFailureException(String reason) {
+			super(reason);
+		}
+	}
+
+
+	static class ReadContentSettingsFailureException extends Exception {
+		/**
+		 * Comment for <code>serialVersionUID</code>
+		 */
+		private static final long serialVersionUID = 1L;
+
+		public ReadContentSettingsFailureException(String reason) {
+			super(reason);
+		}
+	}
+
+	static class WriteContentSettingsFailureException extends Exception {
+		/**
+		 * Comment for <code>serialVersionUID</code>
+		 */
+		private static final long serialVersionUID = 1L;
+
+		public WriteContentSettingsFailureException(String reason) {
+			super(reason);
+		}
+	}
+
+	// writer class for .contentSettings.
+	static class XMLDocumentWriter {
+		OutputStream fOut;
+
+		protected XMLDocumentWriter(OutputStream out) {
+			this.fOut = out;
+		}
+
+		protected final void close() {
+			try {
+				fOut.close();
+			} catch (IOException e) {
+				// do nothing, shouldn't matter
+			}
+		}
+
+		protected void serialize(Document sourceDocument) throws WriteContentSettingsFailureException {
+			// JAXP transformation
+			Source domSource = new DOMSource(sourceDocument);
+			try {
+				Transformer serializer = TransformerFactory.newInstance().newTransformer();
+				try {
+					serializer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+					serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); //$NON-NLS-1$ //$NON-NLS-2$
+				} catch (IllegalArgumentException e) {
+					// unsupported properties
+				}
+				serializer.transform(domSource, new StreamResult(fOut));
+			} catch (TransformerConfigurationException e) {
+				throw new WriteContentSettingsFailureException(e.getMessage());
+			} catch (TransformerFactoryConfigurationError e) {
+				throw new WriteContentSettingsFailureException(e.getMessage());
+			} catch (TransformerException e) {
+				throw new WriteContentSettingsFailureException(e.getMessage());
+			}
+		}
+	}
+
+	public static void main(String[] args) {
+		SimpleNodeOperator a = null;
+		try {
+			a = new SimpleNodeOperator("workspace/org.eclipse.examples.contentsettings/.contentsettings.xml");//$NON-NLS-1$
+		} catch (Exception e) {
+			System.exit(0);
+		}
+
+		// print all Elements
+		//a.printTree(iter);
+
+		// add Element
+		Map attMap = new Hashtable();
+		attMap.put("path", "hogepath");//$NON-NLS-1$ //$NON-NLS-2$
+		attMap.put("fDocument-type", "documenthogehoge");//$NON-NLS-1$ //$NON-NLS-2$
+		a.addElementUnderRoot("file", attMap);//$NON-NLS-1$
+
+		try {
+			a.writeDocument(System.out);
+		} catch (Exception e) {
+			System.err.println(e.toString());
+		}
+
+	}
+
+	//never used
+	//private DOMParser parser;
+	private Document fDocument;
+	private Node root;
+
+	private String settingsFileName;
+
+
+	public SimpleNodeOperator(Document doc) throws CreateContentSettingsFailureException {
+
+		if (doc == null)
+			throw new CreateContentSettingsFailureException("Document doc==null");//$NON-NLS-1$
+		fDocument = doc;
+		root = fDocument.getLastChild();
+		if (root == null)
+			throw new CreateContentSettingsFailureException("Node root==null");//$NON-NLS-1$
+	}
+
+	public SimpleNodeOperator(String fullPath) throws ReadContentSettingsFailureException {
+		this.settingsFileName = fullPath;
+		createObjectOfDocument();
+	}
+
+	// add attribute(attName=attValue) of ele without checking overlapping of
+	// another attributes of ele.
+	// if overlapping ,override
+	protected Node addAttributeAt(Element ele, String attName, String attValue) {
+		Attr att = fDocument.createAttribute(attName);
+		att.setValue(attValue);
+		if (ele != null)
+			ele.setAttributeNode(att);
+		return ele;
+	}
+
+	protected Node addElementUnder(Node parent, String tagName, Map attMap) {
+		if (parent == null || tagName == null)
+			return null;
+		Element e = fDocument.createElement(tagName);
+		if (attMap != null) {
+			if (!attMap.isEmpty()) {
+				Set attKeys = attMap.keySet();
+				Iterator iter = attKeys.iterator();
+				while (iter.hasNext()) {
+					String key = (String) iter.next();
+					e.setAttribute(key, (String) attMap.get(key));
+				}
+			}
+		}
+		parent.appendChild(e);
+		return e;
+	}
+
+	protected final Node addElementUnderRoot(String tagName) {
+		return addElementUnder(root, tagName, null);
+	}
+
+	// add element with attMap as attribute without checking overlapping.
+	protected final Node addElementUnderRoot(String tagName, Map attMap) {
+		return addElementUnder(root, tagName, attMap);
+	}
+
+	private void createObjectOfDocument() throws ReadContentSettingsFailureException {
+		try {
+			fDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(settingsFileName));
+		} catch (SAXException e) {
+			Logger.logException("exception parsing" + settingsFileName, e); //$NON-NLS-1$
+		} catch (IOException e) {
+			Logger.logException("I/O exception parsing" + settingsFileName, e); //$NON-NLS-1$
+		} catch (ParserConfigurationException e) {
+			Logger.logException("exception accessing DOMImplementation", e); //$NON-NLS-1$
+		} catch (FactoryConfigurationError e) {
+			Logger.logException("exception accessing DOMImplementation", e); //$NON-NLS-1$
+		}
+		//get the root of the XML fDocument
+		root = fDocument.getLastChild();
+		if (root == null) {
+			throw new ReadContentSettingsFailureException("Error: Node root==null");//$NON-NLS-1$
+		}
+	}
+
+	protected Map getAttributesOf(Node node) {
+		if (!node.hasAttributes())
+			return null;
+		Map map = new HashMap();
+		NamedNodeMap attrs = node.getAttributes();
+		int size = attrs.getLength();
+		for (int i = 0; i < size; i++) {
+			Attr attr = (Attr) attrs.item(i);
+			map.put(attr.getName(), attr.getValue());
+		}
+		return (map);
+	}
+
+	private Node getElementWithAttribute(Node first, String attName, String attValue) {
+		Node navpoint = first;
+		while (navpoint != null) {
+			if (navpoint.getNodeType() == Node.ELEMENT_NODE) {
+				NamedNodeMap m = navpoint.getAttributes();
+				if (m == null)
+					continue;
+				if (m.getNamedItem(attName) != null) {
+					if (attValue.equals(((Attr) m.getNamedItem(attName)).getNodeValue()))
+						return navpoint;
+				}
+				NodeList childNodes = navpoint.getChildNodes();
+				if (childNodes != null && childNodes.getLength() > 0) {
+					Node holdNode = getElementWithAttribute(navpoint.getFirstChild(), attName, attValue);
+					if (holdNode != null) {
+						return holdNode;
+					}
+				}
+			}
+			navpoint = navpoint.getNextSibling();
+		}
+		return null;
+	}
+
+
+	// return a (first) Element with attr(attName=attValue) it if exists,
+	// otherwise return null
+	protected Node getElementWithAttribute(String attName, String attValue) {
+		if (attName == null || attValue == null || !fDocument.hasChildNodes())
+			return null;
+		return getElementWithAttribute(fDocument.getFirstChild(), attName, attValue);
+	}
+
+	// retrun Element which has nodeName as Node Name
+	protected Node getElementWithNodeName(String nodeName) {
+		if (nodeName == null)
+			return null;
+		NodeList nodes = fDocument.getElementsByTagName(nodeName);
+		if (nodes.getLength() > 0) {
+			return nodes.item(0);
+		}
+		return null;
+	}
+
+	public void printTree(NodeIterator iter) {
+		Node n;
+		while ((n = iter.nextNode()) != null) {
+			System.out.println(n.getNodeName() + ":");//$NON-NLS-1$
+			NamedNodeMap m = n.getAttributes();
+			if (m == null)
+				continue;
+			for (int i = 0; i < m.getLength(); i++) {
+				String attName = m.item(i).getNodeName();
+				System.out.print(" " + attName + "=" + m.item(i).getNodeValue());//$NON-NLS-1$ //$NON-NLS-2$
+			}
+			System.out.println("");//$NON-NLS-1$
+		}
+	}
+
+
+	// remove attribute(attName) at ele.
+	protected Attr removeAttributeAt(Element ele, String attName) {
+		if (ele == null || attName == null)
+			return null;
+		Attr att = ele.getAttributeNode(attName);
+		ele.removeAttribute(attName);
+		return att;
+	}
+
+	protected Element removeElementWith(String nodeName) {
+		NodeList nodes = fDocument.getElementsByTagName(nodeName);
+		for (int i = 0; i < nodes.getLength(); i++) {
+			nodes.item(i).getParentNode().removeChild(nodes.item(i));
+		}
+		return null;
+	}
+
+	// remove a (first) Element with attr(attName=attValue) and return it if
+	// exists, otherwise return null
+	protected Element removeElementWith(String attName, String attValue) {
+		if (fDocument.hasChildNodes()) {
+			Node element = getElementWithAttribute(attName, attValue);
+			if (element != null && element.getNodeType() == Node.ELEMENT_NODE) {
+				element.getParentNode().removeChild(element);
+				return (Element) element;
+			}
+		}
+		return null;
+
+	}
+
+	// update attribute(attName=newValue) at ele if both ele and attribute of
+	// ele exist
+	protected void updateAttributeAt(Element ele, String attName, String newValue) {
+		Attr att = null;
+		if (ele != null)
+			if ((att = ele.getAttributeNode(attName)) != null)
+				att.setValue(newValue);
+	}
+
+	protected void writeDocument(OutputStream out) throws WriteContentSettingsFailureException {
+		XMLDocumentWriter writer = new XMLDocumentWriter(out);
+		try {
+			writer.serialize(fDocument);
+		} finally {
+			writer.close();
+		}
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CodedIO.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CodedIO.java
new file mode 100644
index 0000000..1f31829
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CodedIO.java
@@ -0,0 +1,259 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.util.Properties;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.wst.sse.core.internal.encoding.util.Assert;
+import org.eclipse.wst.sse.core.internal.encoding.util.Logger;
+import org.osgi.framework.Bundle;
+
+
+public abstract class CodedIO {
+
+	private final boolean DEBUG = false;
+	
+	public static final int MAX_BUF_SIZE = 1024 * 8;
+
+	public static final int MAX_MARK_SIZE = MAX_BUF_SIZE;
+
+	public static final String NO_SPEC_DEFAULT = "NoSpecDefault"; //$NON-NLS-1$
+
+	private static Properties overridenCharsets = null;
+
+	/**
+	 * <p>
+	 * There are two well known understood cases where the standard/default
+	 * Java Mappings are not sufficient. (Thanks to Hirotaka Matsumoto for
+	 * providing these two). I believe there are others that individual
+	 * customers have requested to override on a case by case basis, but I've
+	 * lost the details. TODO-future: document some of those use-cases.
+	 * </p>
+	 * <ul>
+	 * <li>ISO-8859-8-I</li>
+	 * <p>
+	 * In the code conversion point of view, ISO-9959-8 and ISO-8859-8-I are
+	 * the same. However. the representation on the browser is different. (
+	 * It's very very hard to explain this into the words, but once you will
+	 * see, you will understand it :) Many BiDi HTML/JSPs use ISO-8859-8-I in
+	 * META/page directive. So WSAD needs to support this encoding.
+	 * </p>
+	 * <li>X-SJIS</li>
+	 * <p>
+	 * Because Mosaic/Navigator 2.0 supported only X-SJIS/X-EUC-JP, lots of
+	 * old HTML files used X-SJIS/X-EUC-JP so that the customers still want us
+	 * to support this code conversion for HTML files.
+	 * </p>
+	 * </ul>
+	 * 
+	 * @param detectedCharsetName
+	 * @return the detectedCharsetName, if no overrides, otherwise the charset
+	 *         name that should be used instead of detectedCharsetName
+	 */
+	/**
+	 * This method is deliberatly 'default access' since clients should not
+	 * need to access this information directly.
+	 */
+	static public String checkMappingOverrides(String detectedCharsetName) {
+		// This method MUST return what was passed in, if
+		// there are no
+		// overrides.
+		String result = detectedCharsetName;
+		String newResult = getOverridenCharsets().getProperty(detectedCharsetName);
+		if (newResult != null) {
+			result = newResult;
+		}
+		return result;
+	}
+
+	/**
+	 * Note: once this instance is created, trace info still needs to be
+	 * appended by caller, depending on the context its created.
+	 */
+	public static EncodingMemento createEncodingMemento(byte[] detectedBom, String javaCharsetName, String detectedCharsetName, String unSupportedName, String specDefaultEncoding, String reason) {
+		EncodingMemento result = new EncodingMemento();
+		result.setJavaCharsetName(javaCharsetName);
+		result.setDetectedCharsetName(detectedCharsetName);
+		// TODO: if detectedCharset and spec default is
+		// null, need to use "work
+		// bench based" defaults.
+		if (specDefaultEncoding == null)
+			result.setAppropriateDefault(NO_SPEC_DEFAULT);
+		else
+			result.setAppropriateDefault(specDefaultEncoding);
+		if (unSupportedName != null) {
+			result.setInvalidEncoding(unSupportedName);
+		}
+		// check if valid
+		try {
+			Charset.isSupported(javaCharsetName);
+		} catch (IllegalCharsetNameException e) {
+			result.setInvalidEncoding(javaCharsetName);
+		}
+
+		// check UTF83ByteBOMUsed and UnicodeStream
+		if (detectedBom != null) {
+			if (detectedBom.length == 2)
+				result.setUnicodeStream(true);
+			else if (detectedBom.length == 3)
+				result.setUTF83ByteBOMUsed(true);
+			result.setUnicodeBOM(detectedBom);
+		}
+		return result;
+	}
+
+	/**
+	 * Note: once this instance is created, trace info still needs to be
+	 * appended by caller, depending on the context its created.
+	 */
+	public static EncodingMemento createEncodingMemento(String detectedCharsetName) {
+		return createEncodingMemento(detectedCharsetName, null);
+	}
+
+	/**
+	 * Note: once this instance is created, trace info still needs to be
+	 * appended by caller, depending on the context its created.
+	 */
+	public static EncodingMemento createEncodingMemento(String detectedCharsetName, String reason) {
+		return createEncodingMemento(detectedCharsetName, reason, null);
+	}
+
+	/**
+	 * Note: once this instance is created, trace info still needs to be
+	 * appended by caller, depending on the context its created.
+	 */
+	public static EncodingMemento createEncodingMemento(String detectedCharsetName, String reason, String specDefaultEncoding) {
+		EncodingMemento result = new EncodingMemento();
+		result = new EncodingMemento();
+		String javaCharset = getAppropriateJavaCharset(detectedCharsetName);
+		result.setJavaCharsetName(javaCharset);
+		result.setDetectedCharsetName(detectedCharsetName);
+		// TODO: if detectedCharset and spec default is
+		// null, need to use "work
+		// bench based" defaults.
+		if (specDefaultEncoding == null)
+			result.setAppropriateDefault(NO_SPEC_DEFAULT);
+		else
+			result.setAppropriateDefault(specDefaultEncoding);
+		// check if valid
+		try {
+			Charset.isSupported(javaCharset);
+		} catch (IllegalCharsetNameException e) {
+			result.setInvalidEncoding(javaCharset);
+		}
+
+		return result;
+	}
+
+	/**
+	 * This method can return null, if invalid charset name (in which case
+	 * "appropriateDefault" should be used, if a name is really need for some
+	 * "save anyway" cases).
+	 * 
+	 * @param detectedCharsetName
+	 * @return
+	 */
+	public static String getAppropriateJavaCharset(String detectedCharsetName) {
+		// we don't allow null argument (or risk NPE or
+		// IllegalArgumentException later at several
+		// points.
+		Assert.isNotNull(detectedCharsetName, "illegal charset argument. it can not be null"); //$NON-NLS-1$
+		String result = detectedCharsetName;
+		// 1. Check explicit mapping overrides from
+		// property file
+		result = CodedIO.checkMappingOverrides(detectedCharsetName);
+		// 2. Use the "canonical" name from JRE mappings
+		// Note: see Charset JavaDoc, the name you get one
+		// with can be alias,
+		// the name you get back is "standard" name.
+		Charset javaCharset = null;
+		// Note: this will immediatly throw
+		// "UnsuppotedCharsetException" if it
+		// invalid. Issue: Is it more client friendly to
+		// eat that exception and return null?
+		javaCharset = Charset.forName(result);
+		if (javaCharset != null) {
+			result = javaCharset.name();
+		}
+		return result;
+	}
+
+	/**
+	 * @return Returns the overridenCharsets.
+	 */
+	private static Properties getOverridenCharsets() {
+		if (overridenCharsets == null) {
+			overridenCharsets = new Properties();
+			Bundle keyBundle = Platform.getBundle(ICodedResourcePlugin.ID);
+			IPath keyPath = new Path("config/override.properties"); //$NON-NLS-1$
+			URL location = Platform.find(keyBundle, keyPath);
+			InputStream propertiesInputStream = null;
+			try {
+				propertiesInputStream = location.openStream();
+				overridenCharsets.load(propertiesInputStream);
+			} catch (IOException e) {
+				// if can't read, just assume there's no
+				// overrides
+				// and repeated attempts will not occur,
+				// since they
+				// will be represented by an empty
+				// Properties object
+			}
+		}
+		return overridenCharsets;
+	}
+
+	/**
+	 * This class need not be instantiated (though its subclasses can be).
+	 */
+	protected CodedIO() {
+		super();
+	}
+
+	protected EncodingMemento createMemento(IContentDescription contentDescription) {
+		EncodingMemento result;
+		String appropriateDefault = contentDescription.getContentType().getDefaultCharset();
+		String detectedCharset = (String) contentDescription.getProperty(IContentDescriptionExtended.DETECTED_CHARSET);
+		String unSupportedCharset = (String) contentDescription.getProperty(IContentDescriptionExtended.UNSUPPORTED_CHARSET);
+		String javaCharset = contentDescription.getCharset();
+		// integrity checks for debugging
+		if (javaCharset == null) {
+			Logger.log(Logger.INFO_DEBUG, "charset equaled null!"); //$NON-NLS-1$
+		} else if (javaCharset.length() == 0) {
+			Logger.log(Logger.INFO_DEBUG, "charset equaled emptyString!"); //$NON-NLS-1$
+		}
+		byte[] BOM = (byte[]) contentDescription.getProperty(IContentDescription.BYTE_ORDER_MARK);
+		//result = (EncodingMemento)
+		// contentDescription.getProperty(IContentDescriptionExtended.ENCODING_MEMENTO);
+		result = createEncodingMemento(BOM, javaCharset, detectedCharset, unSupportedCharset, appropriateDefault, null);
+		if (!result.isValid()) {
+			result.setAppropriateDefault(appropriateDefault);
+			// integrity check for debugging "invalid" cases.
+			// the apprriate default we have, should equal what's in the
+			// detected field. (not sure this is always required)
+			if (DEBUG && appropriateDefault != null && !appropriateDefault.equals(detectedCharset)) {
+				Logger.log(Logger.INFO_DEBUG, "appropriate did not equal detected, as expected for invalid charset case"); //$NON-NLS-1$
+			}
+		}
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CodedReaderCreator.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CodedReaderCreator.java
new file mode 100644
index 0000000..155ccdb
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CodedReaderCreator.java
@@ -0,0 +1,542 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CodingErrorAction;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentTypeManager;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.wst.sse.core.internal.SSECoreMessages;
+import org.eclipse.wst.sse.core.internal.encoding.util.Assert;
+import org.eclipse.wst.sse.core.internal.encoding.util.BufferedLimitedStream;
+import org.eclipse.wst.sse.core.internal.encoding.util.Logger;
+import org.eclipse.wst.sse.core.internal.encoding.util.NullInputStream;
+import org.eclipse.wst.sse.core.internal.encoding.util.UnicodeBOMEncodingDetector;
+import org.eclipse.wst.sse.core.internal.exceptions.UnsupportedCharsetExceptionWithDetail;
+
+
+/**
+ * The purpose of this class is to centralize analysis of a file to determine
+ * the most appropriate rules of decoding it. The intended use is to set the
+ * input, then get the reader for that input which will have its encoding set
+ * appropriately. Additionally, there is an EncodingMemento provided, which
+ * will be required, in some cases, to later determine the most appropriate
+ * form of encoded output.
+ */
+public class CodedReaderCreator extends CodedIO {
+
+
+	private boolean fClientSuppliedStream;
+
+
+	private EncodingMemento fEncodingMemento;
+
+	private EncodingRule fEncodingRule;
+
+	private String fFilename;
+
+	private IFile fIFile;
+
+
+	private InputStream fInputStream;
+	
+	private static final String CHARSET_UTF_16= "UTF-16"; //$NON-NLS-1$
+	
+	private static final String CHARSET_UTF_16LE= "UTF-16LE"; //$NON-NLS-1$
+
+	public CodedReaderCreator() {
+
+		super();
+	}
+
+	public CodedReaderCreator(IFile file) throws CoreException, IOException {
+
+		this();
+		set(file);
+		setEncodingRule(EncodingRule.CONTENT_BASED);
+	}
+
+	public CodedReaderCreator(IFile file, EncodingRule encodingRule) throws CoreException, IOException {
+
+		this();
+		set(file);
+		setEncodingRule(encodingRule);
+	}
+
+	public CodedReaderCreator(String filename, InputStream inputStream) {
+
+		this();
+		set(filename, inputStream);
+		setEncodingRule(EncodingRule.CONTENT_BASED);
+	}
+
+	public CodedReaderCreator(String filename, InputStream inputStream, EncodingRule encodingRule) {
+
+		this();
+		set(filename, inputStream);
+		setEncodingRule(encodingRule);
+	}
+
+	private EncodingMemento checkForEncodingInContents(InputStream limitedStream) throws CoreException, IOException {
+		EncodingMemento result = null;
+
+		// if encoding memento already set, then iFile must
+		// have been set, and no need to get again.
+		if (fEncodingMemento != null) {
+			result = fEncodingMemento;
+		}
+		else {
+			if (fClientSuppliedStream) {
+				try {
+					limitedStream.reset();
+					IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
+					IContentDescription contentDescription = contentTypeManager.getDescriptionFor(limitedStream, fFilename, IContentDescription.ALL);
+					if (contentDescription != null) {
+						fEncodingMemento = createMemento(contentDescription);
+					}
+					result = fEncodingMemento;
+				}
+				finally {
+					limitedStream.reset();
+				}
+			}
+			else {
+				// throw new IllegalStateException("unexpected state:
+				// encodingMemento was null but no input stream supplied by
+				// client"); //$NON-NLS-1$
+				result = null;
+			}
+		}
+
+		if (result != null && !result.isValid() && !forceDefault()) {
+			throw new UnsupportedCharsetExceptionWithDetail(result);
+		}
+
+		return result;
+	}
+
+	/**
+	 * @param resettableLimitedStream
+	 */
+	private EncodingMemento checkStreamForBOM(InputStream resettableLimitedStream) {
+		EncodingMemento result = null;
+		UnicodeBOMEncodingDetector unicodeBOMEncodingDetector = new UnicodeBOMEncodingDetector();
+		unicodeBOMEncodingDetector.set(resettableLimitedStream);
+		result = unicodeBOMEncodingDetector.getEncodingMemento();
+		return result;
+	}
+
+	/**
+	 * @param iFile
+	 * @throws CoreException
+	 * @throws IOException
+	 */
+	private EncodingMemento findMementoFromFileCase() throws CoreException, IOException {
+		EncodingMemento result = null;
+		IContentDescription contentDescription = null;
+		try {
+			// This method provides possible improved performance at the
+			// cost of sometimes returning null
+			if (fIFile.exists())
+				contentDescription = fIFile.getContentDescription();
+		}
+		catch (CoreException e) {
+			// Assume if core exception occurs, we can still try more
+			// expensive
+			// discovery options.
+			Logger.logException(e);
+		}
+		if (contentDescription == null && fIFile.isAccessible()) {
+			InputStream contents = null;
+			try {
+				contents = fIFile.getContents();
+				contentDescription = Platform.getContentTypeManager().getDescriptionFor(contents, fIFile.getName(), IContentDescription.ALL);
+			}
+			catch (CoreException e1) {
+				// Assume if core exception occurs, we can't really do much
+				// with
+				// determining encoding, etc.
+				Logger.logException(e1);
+				throw e1;
+			}
+			catch (IOException e2) {
+				// We likely couldn't get the contents of the file, something
+				// is really wrong
+				Logger.logException(e2);
+				throw e2;
+			}
+			if (contents != null) {
+				try {
+					contents.close();
+				}
+				catch (IOException e2) {
+					Logger.logException(e2);
+				}
+			}
+		}
+		if (contentDescription != null) {
+			result = createMemento(contentDescription);
+		}
+
+		return result;
+	}
+
+	/**
+	 * The primary method which contains the highest level rules for how to
+	 * decide appropriate decoding rules: 1. first check for unicode stream 2.
+	 * then looked for encoding specified in content (according to the type of
+	 * content that is it ... xml, html, jsp, etc. 3. then check for various
+	 * settings: file settings first, if null check project settings, if null,
+	 * check user preferences. 4. lastly (or, what is the last user
+	 * preference) is to use "workbench defaults".
+	 * 
+	 * @throws IOException
+	 * @throws CoreException
+	 */
+	private EncodingMemento findMementoFromStreamCase() throws CoreException, IOException {
+
+		EncodingMemento result = null;
+		InputStream resettableLimitedStream = null;
+		try {
+			resettableLimitedStream = getLimitedStream(getResettableStream());
+			if (resettableLimitedStream != null) {
+				// first check for unicode stream
+				result = checkStreamForBOM(resettableLimitedStream);
+				// if not that, then check contents
+				if (result == null) {
+					resettableLimitedStream.reset();
+					result = checkForEncodingInContents(resettableLimitedStream);
+				}
+
+			}
+			else {
+				// stream null, may name's not.
+				if (fFilename != null) {
+					// filename not null
+					IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
+					IContentDescription contentDescription = contentTypeManager.getDescriptionFor(new NullInputStream(), fFilename, IContentDescription.ALL);
+					if (contentDescription != null) {
+						result = createMemento(contentDescription);
+					}
+				}
+			}
+		}
+		finally {
+			if (resettableLimitedStream != null) {
+				handleStreamClose(resettableLimitedStream);
+			}
+		}
+		return result;
+	}
+
+	private boolean forceDefault() {
+
+		boolean result = false;
+		if (fEncodingRule != null && fEncodingRule == EncodingRule.FORCE_DEFAULT)
+			result = true;
+		return result;
+	}
+
+	public Reader getCodedReader() throws CoreException, IOException {
+
+		Reader result = null;
+		// we make a local copy of encoding memento so
+		// stream won't
+		// be accessed simultaneously.
+		EncodingMemento encodingMemento = getEncodingMemento();
+		Assert.isNotNull(encodingMemento, "Appears reader requested before file or stream set"); //$NON-NLS-1$
+		InputStream streamToReturn = getResettableStream();
+		streamToReturn.reset();
+		// if UTF 3 byte BOM is used (or UTF-16LE), the
+		// built in converters
+		// don't
+		// correct skip all three bytes ... so skip
+		// remaining one to leave
+		// stream transparently ready for client.
+		// see ... TODO look up bug number
+		if (encodingMemento.isUnicodeStream()) {
+			streamToReturn.skip(2);
+		}
+		else if (encodingMemento.isUTF83ByteBOMUsed()) {
+			streamToReturn.skip(3);
+		}
+		String charsetName = encodingMemento.getJavaCharsetName();
+		if (charsetName == null) {
+			charsetName = encodingMemento.getDetectedCharsetName();
+		}
+		if (!encodingMemento.isValid() && !forceDefault()) {
+			throw new UnsupportedCharsetExceptionWithDetail(encodingMemento);
+		}
+
+		if (fEncodingRule == EncodingRule.FORCE_DEFAULT) {
+			charsetName = encodingMemento.getAppropriateDefault();
+		}
+		
+		// [228366] For files that have a unicode BOM, and a charset name of UTF-16, the charset decoder needs "UTF-16LE"
+		if(CHARSET_UTF_16.equals(charsetName) && encodingMemento.getUnicodeBOM() == IContentDescription.BOM_UTF_16LE)
+			charsetName = CHARSET_UTF_16LE;
+		
+		Charset charset = Charset.forName(charsetName);
+		CharsetDecoder charsetDecoder = charset.newDecoder();
+		if (fEncodingRule == EncodingRule.IGNORE_CONVERSION_ERROR) {
+			charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE);
+			charsetDecoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+		}
+		else {
+			charsetDecoder.onMalformedInput(CodingErrorAction.REPORT);
+			charsetDecoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+		}
+		// more efficient to be buffered, and I know of no
+		// reason not to return
+		// that directly.
+		result = new BufferedReader(new InputStreamReader(streamToReturn, charsetDecoder), CodedIO.MAX_BUF_SIZE);
+		result.mark(CodedIO.MAX_BUF_SIZE);
+		return result;
+	}
+
+	public EncodingMemento getEncodingMemento() throws CoreException, IOException {
+		// figure out encoding memento from encoding strategy
+		if (fEncodingMemento == null) {
+			if (fClientSuppliedStream) {
+				fEncodingMemento = findMementoFromStreamCase();
+			}
+			else if (fIFile != null) {
+				fEncodingMemento = findMementoFromFileCase();
+			}
+		}
+
+		// if encoding stratagy doesn't provide answer,
+		// then try file settings, project settings,
+		// user preferences, and
+		// finally workbench default.
+		//
+		if (fEncodingMemento == null || fEncodingMemento.getDetectedCharsetName() == null) {
+			fEncodingMemento = getEncodingMementoFromResourceAndPreference();
+		}
+
+		// use DefaultNameRules from NonContentBasedEncodingRules as the final
+		// default
+		if (fEncodingMemento == null) {
+			fEncodingMemento = handleNotProvidedFromContentCase();
+		}
+
+		return fEncodingMemento;
+	}
+
+	/*
+	 * This method is called only when encoding is not detected in the file.
+	 * 
+	 * Here is encoding lookup order we will try: - try resource content
+	 * description (Eclipse Text file encoding) - try resource content
+	 * properties (for JSP only) - try content type encoding preferences (for
+	 * HTML only) - try resource content description (Eclipse Text file
+	 * encoding, implicit check)
+	 * 
+	 * Note: This method appears in both CodedReaderCreator and
+	 * CodedStreamCreator (with just a minor difference). They should be kept
+	 * the same.
+	 */
+	private EncodingMemento getEncodingMementoFromResourceAndPreference() throws IOException, CoreException {
+		EncodingMemento encodingMemento = fEncodingMemento;
+
+		// Follow Eclipse Platform's direction. Get the charset from IFile.
+		if (fIFile != null) {
+			String charset = fIFile.getCharset();
+			encodingMemento = CodedIO.createEncodingMemento(charset);
+		}
+
+		return encodingMemento;
+	}
+
+	/**
+	 * Ensures that an InputStream has mark/reset support, is readlimit is
+	 * set, and that the stream is "limitable" (that is, reports "end of
+	 * input" rather than allow going past mark). This is very specialized
+	 * stream introduced to overcome
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=67211. See also
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=68565
+	 */
+	private InputStream getLimitedStream(InputStream original) {
+		if (original == null)
+			return null;
+		if (original instanceof BufferedLimitedStream)
+			return original;
+		InputStream s = new BufferedLimitedStream(original, CodedIO.MAX_MARK_SIZE);
+		s.mark(CodedIO.MAX_MARK_SIZE);
+		return s;
+	}
+
+	private InputStream getResettableStream() throws CoreException, IOException {
+
+		InputStream resettableStream = null;
+
+		if (fIFile != null) {
+			InputStream inputStream = null;
+			try {
+				// note we always get contents, even if out of synch
+				inputStream = fIFile.getContents(true);
+			}
+			catch (CoreException e) {
+				// SHOULD actually check for existence of
+				// fIStorage, but
+				// for now will just assume core exception
+				// means it
+				// doesn't exist on file system, yet.
+				// and we'll log, just in case its a noteable error
+				Logger.logException(e);
+				inputStream = new NullInputStream();
+			}
+			resettableStream = new BufferedInputStream(inputStream, CodedIO.MAX_BUF_SIZE);
+		}
+		else {
+			if (fInputStream != null) {
+				if (fInputStream.markSupported()) {
+					resettableStream = fInputStream;
+					// try {
+					resettableStream.reset();
+					// }
+					// catch (IOException e) {
+					// // assumed just hasn't been marked yet, so ignore
+					// }
+				}
+				else {
+					resettableStream = new BufferedInputStream(fInputStream, CodedIO.MAX_BUF_SIZE);
+				}
+			}
+		}
+
+		if (resettableStream == null) {
+			resettableStream = new NullInputStream();
+		}
+
+		// mark this once, stream at "zero" position
+		resettableStream.mark(MAX_MARK_SIZE);
+		return resettableStream;
+	}
+
+	private EncodingMemento handleNotProvidedFromContentCase() {
+
+		EncodingMemento result = null;
+		String specDefault = null;
+		// try {
+		// specDefault = getEncodingDetector().getSpecDefaultEncoding();
+		// }
+		// catch (CoreException e) {
+		// // If this exception occurs, assumes there is
+		// // no specDefault
+		// }
+		// catch (IOException e) {
+		// // If this exception occurs, assumes there is
+		// // no specDefault
+		// }
+		// finally {
+		// try {
+		// handleStreamClose(fEncodingDetectorStream);
+		// }
+		// catch (IOException e1) {
+		// // severe error, not much to do here
+		// }
+		// }
+		// this logic should be moved to 'detection' if not already
+		String charset = NonContentBasedEncodingRules.useDefaultNameRules(specDefault);
+		Assert.isNotNull(charset, "post condition failed"); //$NON-NLS-1$
+		result = CodedIO.createEncodingMemento(charset);
+		return result;
+	}
+
+	/**
+	 * @param resettableInputStream
+	 * @throws IOException
+	 */
+	private void handleStreamClose(InputStream resettableInputStream) throws IOException {
+
+		if (resettableInputStream != null) {
+			if (fClientSuppliedStream) {
+				resettableInputStream.reset();
+			}
+			else {
+
+				resettableInputStream.close();
+			}
+		}
+	}
+
+	// TODO We just copy the content properties encoding to current resource's
+	// encoding for now. May improve the UI later by setting an informational
+	// message and/or disable the content properties encoding field.
+	// TODO: remake private else remove
+	void migrateContentPropertiesEncoding(String encoding) throws CoreException {
+		final IFile file = fIFile;
+		final String charset = encoding;
+		// TODO: externalize string later
+		Job migrater = new Job(SSECoreMessages.Migrate_Charset) { //$NON-NLS-1$
+			protected IStatus run(IProgressMonitor monitor) {
+				if (file != null) {
+					try {
+						file.setCharset(charset, null);
+					}
+					catch (CoreException e) {
+						Logger.logException(e);
+					}
+				}
+				return Status.OK_STATUS;
+			}
+		};
+		migrater.setSystem(true);
+		migrater.schedule();
+	}
+
+	private void resetAll() {
+
+		fEncodingRule = null;
+		fIFile = null;
+		fFilename = null;
+		fInputStream = null;
+		fEncodingMemento = null;
+		fClientSuppliedStream = false;
+	}
+
+	public void set(IFile iFile) throws CoreException, IOException {
+		Assert.isNotNull(iFile, "illegal argument"); //$NON-NLS-1$
+		resetAll();
+		fIFile = iFile;
+	}
+
+	public void set(String filename, InputStream inputStream) {
+
+		resetAll();
+		fFilename = filename;
+		fInputStream = inputStream;
+		fClientSuppliedStream = true;
+	}
+
+	public void setEncodingRule(EncodingRule encodingRule) {
+
+		fEncodingRule = encodingRule;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CodedStreamCreator.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CodedStreamCreator.java
new file mode 100644
index 0000000..ac1224c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CodedStreamCreator.java
@@ -0,0 +1,509 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.StringReader;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.UnmappableCharacterException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentTypeManager;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.wst.sse.core.internal.SSECoreMessages;
+import org.eclipse.wst.sse.core.internal.SSECorePlugin;
+import org.eclipse.wst.sse.core.internal.encoding.util.Assert;
+import org.eclipse.wst.sse.core.internal.encoding.util.Logger;
+import org.eclipse.wst.sse.core.internal.exceptions.CharConversionErrorWithDetail;
+import org.eclipse.wst.sse.core.internal.exceptions.MalformedOutputExceptionWithDetail;
+import org.eclipse.wst.sse.core.internal.exceptions.UnsupportedCharsetExceptionWithDetail;
+
+
+public class CodedStreamCreator extends CodedIO {
+
+	private final static int INITIAL_BUFFER_SIZE = 1024 * 16;
+
+	// the 32 bytes used by default by ByteOutputStream is
+	// a little small
+	private static final String PROGRAM_ERROR__FAILED_TO_FIND_ANY_CHARSET_ANYWHERE_ = "Program error: failed to find any charset anywhere!"; //$NON-NLS-1$
+
+	private static final String UTF_16BE_CHARSET_NAME = "UTF-16BE"; //$NON-NLS-1$
+	private static final String UTF_16LE_CHARSET_NAME = "UTF-16LE"; //$NON-NLS-1$
+	//	private static final String UTF_16_CHARSET_NAME = "UTF-16";
+	// //$NON-NLS-1$
+
+	private static final String UTF_8_CHARSET_NAME = "UTF-8"; //$NON-NLS-1$
+
+	private boolean fClientSuppliedReader;
+
+	// future_TODO: this 'checkConversion' can be a little
+	// pricey for large
+	// files, chould be a user preference, or something.
+	// private static final boolean checkConversion = true;
+	private EncodingMemento fCurrentEncodingMemento;
+
+	private EncodingMemento fEncodingMemento;
+
+	private String fFilename;
+
+	private boolean fHasBeenAnalyzed;
+
+	private IFile fIFile;
+
+	private EncodingMemento fPreviousEncodingMemento;
+
+	private Reader fReader;
+
+	private Reader fResettableReader;
+	private byte[] UTF16BEBOM = new byte[]{(byte) 0xFE, (byte) 0xFF};
+
+	private byte[] UTF16LEBOM = new byte[]{(byte) 0xFF, (byte) 0xFE};
+	private byte[] UTF3BYTEBOM = new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF};
+
+	public CodedStreamCreator() {
+		super();
+	}
+
+	public CodedStreamCreator(String filename, char[] characterArray) {
+		super();
+		fFilename = filename;
+		fReader = new CharArrayReader(characterArray);
+	}
+
+	public CodedStreamCreator(String filename, Reader reader) {
+		super();
+		fFilename = filename;
+		fReader = reader;
+	}
+
+	public CodedStreamCreator(String filename, String textString) {
+		super();
+		fFilename = filename;
+		fReader = new StringReader(textString);
+	}
+
+	/**
+	 * The primary method which contains the highest level rules for how to
+	 * decide appropriate decoding rules: 1. first check for unicode stream 2.
+	 * then looked for encoding specified in content (according to the type of
+	 * content that is it ... xml, html, jsp, etc. 3. then check for various
+	 * settings: file settings first, if null check project settings, if null,
+	 * check user preferences. 4. lastly (or, what is the last user
+	 * preference) is to use "workbench defaults".
+	 */
+	private void analyze() throws CoreException, IOException {
+		Reader resettableReader = getResettableReader();
+		try {
+			if (fCurrentEncodingMemento == null) {
+				resettableReader.reset();
+				fCurrentEncodingMemento = checkForEncodingInContents();
+			}
+			// if encoding stratagy doesn't provide answer,
+			// then try file settings, project settings,
+			// user preferences, and
+			// finally workbench default.
+			//
+			if (fCurrentEncodingMemento == null || fCurrentEncodingMemento.getDetectedCharsetName() == null) {
+				resettableReader.reset();
+				fCurrentEncodingMemento = getEncodingMementoFromResourceAndPreference();
+			}
+
+			// use DefaultNameRules from NonContentBasedEncodingRules as the
+			// final default
+			if (fEncodingMemento == null) {
+				handleNotProvidedFromContentCase();
+			}
+
+			fHasBeenAnalyzed = true;
+		} finally {
+			if (resettableReader != null) {
+				resettableReader.reset();
+			}
+		}
+	}
+
+	/**
+	 * Need to check conversion early on. There's some danger than old
+	 * contents of a file are set to empty, if an exception occurs.
+	 * 
+	 * @param allText
+	 * @param encoding
+	 * @param encodingRule
+	 * @throws java.io.UnsupportedEncodingException
+	 * @throws MalformedOutputExceptionWithDetail
+	 * @deprecated - we need to find "cheaper" way to to this functionality so
+	 *             likely to go away in future
+	 */
+	private void checkConversion(EncodingMemento memento, EncodingRule encodingRule) throws IOException {
+		String javaEncoding = memento.getJavaCharsetName();
+		String detectedEncoding = memento.getDetectedCharsetName();
+		Charset charset = Charset.forName(javaEncoding);
+		CharsetEncoder charsetEncoder = charset.newEncoder();
+		charsetEncoder.onMalformedInput(CodingErrorAction.REPORT);
+		charsetEncoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+		Reader reader = getResettableReader();
+		reader.reset();
+		int currentChar = reader.read();
+		int currentPos = 1;
+		try {
+			while (currentChar != -1) {
+				// note: this can probably be made more
+				// efficient later to
+				// check buffer by buffer, instead of
+				// character by character.
+				try {
+					boolean canConvert = charsetEncoder.canEncode((char) currentChar);
+					if (!canConvert) {
+						if (encodingRule == EncodingRule.IGNORE_CONVERSION_ERROR) {
+							// if we're told to ignore the
+							// encoding conversion
+							// error,
+							// notice we still want to detect
+							// and log it. We simply
+							// don't throw the exception, and
+							// we do continue with
+							// the
+							// save.
+							Logger.log(Logger.ERROR, "Encoding Conversion Error during save"); //$NON-NLS-1$
+						} else {
+							throw new MalformedOutputExceptionWithDetail(javaEncoding, detectedEncoding, currentPos);
+						}
+					}
+					currentChar = reader.read();
+					currentPos++;
+				}
+				// IBM's JRE seems to throw NPE when DBCS char is given to
+				// SBCS charsetEncoder
+				catch (NullPointerException e) {
+					throw new CharConversionErrorWithDetail(javaEncoding); //$NON-NLS-1$
+				}
+			}
+			// if we get all the way through loop without throwing exception,
+			// then there must
+			// be an error not detectable when going character by character.
+			throw new CharConversionErrorWithDetail(javaEncoding); //$NON-NLS-1$
+		} finally {
+			reader.reset();
+		}
+	}
+
+	private EncodingMemento checkForEncodingInContents() throws CoreException, IOException {
+		EncodingMemento result = null;
+
+		// if encoding memento already set, and no need to get again.
+		if (fEncodingMemento != null) {
+			result = fEncodingMemento;
+		} else {
+			if (fClientSuppliedReader) {
+				fReader.reset();
+				IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
+				try {
+					IContentDescription contentDescription = contentTypeManager.getDescriptionFor(fReader, fFilename, IContentDescription.ALL);
+					if (contentDescription != null) {
+						fEncodingMemento = createMemento(contentDescription);
+					} else {
+						fEncodingMemento = CodedIO.createEncodingMemento("UTF-8"); //$NON-NLS-1$
+					}
+				} catch (NullPointerException e) {
+					// TODO: work around for 5/14 bug in base, should be
+					// removed when move up to 5/21
+					// just created a simple default one
+					fEncodingMemento = CodedIO.createEncodingMemento("UTF-8"); //$NON-NLS-1$
+				}
+				result = fEncodingMemento;
+			} else {
+				throw new IllegalStateException("unexpected state: encodingMemento was null but no input stream supplied"); //$NON-NLS-1$
+			}
+		}
+		//		try {
+		//			result = getEncodingDetector().getEncodingMemento();
+		//			if (result != null && !result.isValid() && !forceDefault()) {
+		//				throw new UnsupportedCharsetExceptionWithDetail(result);
+		//			}
+		//		}
+		//		finally {
+		//			handleStreamClose(fEncodingDetectorStream);
+		//		}
+		return result;
+	}
+
+
+	private void dump(OutputStream outputStream, EncodingRule encodingRule, boolean use3ByteBOMifUTF8) throws CoreException, IOException {
+		getCurrentEncodingMemento();
+		String javaEncodingName = null;
+		if (encodingRule == EncodingRule.CONTENT_BASED) {
+			if (fCurrentEncodingMemento.isValid()) {
+				javaEncodingName = fCurrentEncodingMemento.getJavaCharsetName();
+			} else {
+				throw new UnsupportedCharsetExceptionWithDetail(fCurrentEncodingMemento);
+			}
+		} else if (encodingRule == EncodingRule.IGNORE_CONVERSION_ERROR)
+			javaEncodingName = fCurrentEncodingMemento.getJavaCharsetName();
+		else if (encodingRule == EncodingRule.FORCE_DEFAULT)
+			javaEncodingName = fCurrentEncodingMemento.getAppropriateDefault();
+		// write appropriate "header" unicode BOM bytes
+		// Note: Java seems to write appropriate header for
+		// UTF-16, but not
+		// UTF-8 nor UTF-16BE. This
+		// may vary by JRE version, so need to test well.
+		// Note: javaEncodingName can be null in invalid
+		// cases, so we no hard
+		// to skip whole check if that's the case.
+		if (javaEncodingName != null) {
+			if ((javaEncodingName.equals(UTF_8_CHARSET_NAME) && use3ByteBOMifUTF8) || (javaEncodingName.equals(UTF_8_CHARSET_NAME) && fCurrentEncodingMemento.isUTF83ByteBOMUsed())) {
+				outputStream.write(UTF3BYTEBOM);
+			} else if (javaEncodingName.equals(UTF_16LE_CHARSET_NAME)) {
+				outputStream.write(UTF16LEBOM);
+			} else if (javaEncodingName.equals(UTF_16BE_CHARSET_NAME)) {
+				outputStream.write(UTF16BEBOM);
+			}
+		}
+		// TODO add back in line delimiter handling the
+		// "right" way (updating
+		// markers, not requiring string, etc. .. may need
+		// to move to document
+		// level)
+		//allTextBuffer =
+		// handleLineDelimiter(allTextBuffer, document);
+		Reader reader = getResettableReader();
+		// be sure to test large "readers" ... we'll need
+		// to make sure they all
+		// can reset to initial position (StringReader,
+		// CharArrayReader, and
+		// DocumentReader should all work ok).
+		reader.reset();
+		// There must be cleaner logic somehow, but the
+		// idea is that
+		// javaEncodingName can be null
+		// if original detected encoding is not valid (and
+		// if FORCE_DEFAULT was
+		// not specified). Hence, we WANT the first
+		// Charset.forName to
+		// throw appropriate exception.
+		Charset charset = null;
+
+		// this call checks "override" properties file
+		javaEncodingName = CodedIO.getAppropriateJavaCharset(javaEncodingName);
+
+		if (javaEncodingName == null) {
+			charset = Charset.forName(fCurrentEncodingMemento.getDetectedCharsetName());
+		} else {
+			charset = Charset.forName(javaEncodingName);
+		}
+		CharsetEncoder charsetEncoder = charset.newEncoder();
+		if (!(encodingRule == EncodingRule.IGNORE_CONVERSION_ERROR)) {
+			charsetEncoder.onMalformedInput(CodingErrorAction.REPORT);
+			charsetEncoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+		} else {
+			charsetEncoder.onMalformedInput(CodingErrorAction.REPLACE);
+			charsetEncoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+
+		}
+		OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, charsetEncoder);
+		//TODO: this may no longer be needed (and is at
+		// least wrong spot for
+		// it).
+		//		if (checkConversion && (!(encodingRule ==
+		// EncodingRule.IGNORE_CONVERSION_ERROR))) {
+		//			checkConversion(fCurrentEncodingMemento,
+		// encodingRule);
+		//		}
+		char[] charbuf = new char[CodedIO.MAX_BUF_SIZE];
+		int nRead = 0;
+		try {
+			while (nRead != -1) {
+				nRead = reader.read(charbuf, 0, MAX_BUF_SIZE);
+				if (nRead > 0) {
+					outputStreamWriter.flush();
+					outputStreamWriter.write(charbuf, 0, nRead);
+				}
+			}
+		} catch (UnmappableCharacterException e) {
+			checkConversion(fCurrentEncodingMemento, encodingRule);
+		} finally {
+			// since we don't own the original output stream, we
+			// won't close it ours.
+			// the caller who passed it to us must close original one
+			// when appropriate.
+			// (but we do flush to be sure all up-to-date)
+			outputStreamWriter.flush();
+		}
+	}
+
+	private boolean get3ByteBOMPreference() {
+		return SSECorePlugin.getDefault().getPluginPreferences().getBoolean(CommonEncodingPreferenceNames.USE_3BYTE_BOM_WITH_UTF8);
+	}
+
+	public ByteArrayOutputStream getCodedByteArrayOutputStream() throws CoreException, IOException {
+		return getCodedByteArrayOutputStream(EncodingRule.CONTENT_BASED);
+	}
+
+	public ByteArrayOutputStream getCodedByteArrayOutputStream(EncodingRule encodingRule) throws CoreException, IOException {
+		//Assert.isNotNull(fPreviousEncodingMemento,
+		// "previousEncodingMemento
+		// needs to be set first");
+		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
+		dump(byteArrayOutputStream, encodingRule, get3ByteBOMPreference());
+		return byteArrayOutputStream;
+	}
+
+	public EncodingMemento getCurrentEncodingMemento() throws CoreException, IOException {
+		//Assert.isNotNull(fPreviousEncodingMemento,
+		// "previousEncodingMemento
+		// needs to be set first");
+		if (!fHasBeenAnalyzed) {
+			analyze();
+		}
+		// post condition
+		Assert.isNotNull(fCurrentEncodingMemento, "illegal post condition state"); //$NON-NLS-1$
+		// be sure to carry over appropriate encoding
+		// "state" that may be
+		// relevent.
+		if (fPreviousEncodingMemento != null) {
+			fCurrentEncodingMemento.setUTF83ByteBOMUsed(fPreviousEncodingMemento.isUTF83ByteBOMUsed());
+		}
+		return fCurrentEncodingMemento;
+	}
+
+	/*
+	 * This method is called only when encoding is not detected in the file.
+	 * 
+	 * Here is encoding lookup order we will try: - try resource content
+	 * description (Eclipse Text file encoding) - try resource content
+	 * properties (for JSP only) - try content type encoding preferences (for
+	 * HTML only) - try resource content description (Eclipse Text file
+	 * encoding, implicit check)
+	 * 
+	 * Note: This method appears in both CodedReaderCreator and
+	 * CodedStreamCreator (with just a minor difference). They should be kept
+	 * the same.
+	 */
+	private EncodingMemento getEncodingMementoFromResourceAndPreference() throws IOException, CoreException {
+		EncodingMemento encodingMemento = fEncodingMemento;
+
+		// Follow Eclipse Platform's direction. Get the charset from IFile.
+		if (fIFile != null) {
+			String charset = fIFile.getCharset();
+			encodingMemento = CodedIO.createEncodingMemento(charset);
+		}
+
+		return encodingMemento;
+	}
+
+	private Reader getResettableReader() {
+		if (fResettableReader == null) {
+			if (fReader.markSupported()) {
+				fResettableReader = fReader;
+			} else {
+				fResettableReader = new BufferedReader(fReader);
+				try {
+					fResettableReader.mark(MAX_MARK_SIZE);
+				} catch (IOException e) {
+					// impossible, since we just checked if
+					// markable
+					throw new Error(e);
+				}
+
+			}
+		}
+		return fResettableReader;
+	}
+
+	protected void handleNotProvidedFromContentCase() {
+		// move to "detectors" if not already
+		String specDefault = null;
+		//specDefault = getEncodingDetector().getSpecDefaultEncoding();
+		String charset = NonContentBasedEncodingRules.useDefaultNameRules(specDefault);
+		Assert.isNotNull(charset, PROGRAM_ERROR__FAILED_TO_FIND_ANY_CHARSET_ANYWHERE_);
+		fCurrentEncodingMemento = CodedIO.createEncodingMemento(charset);
+	}
+
+	// TODO We just copy the content properties encoding to current resource's
+	// encoding for now. May improve the UI later by setting an informational
+	// message and/or disable the content properties encoding field.
+	// TODO make priviate if needed, else remove
+	void migrateContentPropertiesEncoding(String encoding) throws CoreException {
+		if (fIFile != null)
+			fIFile.setCharset(encoding, null);
+		final IFile file = fIFile;
+		final String charset = encoding;
+		// TODO: externalize string later
+		Job migrater = new Job(SSECoreMessages.Migrate_Charset) { //$NON-NLS-1$
+			protected IStatus run(IProgressMonitor monitor) {
+				if (file != null) {
+					try {
+						file.setCharset(charset, null);
+					} catch (CoreException e) {
+						Logger.logException(e);
+					}
+				}
+				return Status.OK_STATUS;
+			}
+		};
+		migrater.setSystem(true);
+		migrater.schedule();
+
+	}
+
+	/**
+	 *  
+	 */
+	private void resetAll() {
+		fFilename = null;
+		fReader = null;
+		fPreviousEncodingMemento = null;
+		fCurrentEncodingMemento = null;
+		fHasBeenAnalyzed = false;
+		fClientSuppliedReader = false;
+	}
+
+	public void set(IFile file, Reader reader) {
+		fIFile = file;
+		set(file.getName(), reader);
+	}
+
+	public void set(String filename, char[] characterArray) {
+		resetAll();
+		fFilename = filename;
+		fReader = new CharArrayReader(characterArray);
+	}
+
+	public void set(String filename, Reader reader) {
+		resetAll();
+		fFilename = filename;
+		fReader = reader;
+		fClientSuppliedReader = true;
+	}
+
+	public void set(String filename, String textString) {
+		set(filename, new StringReader(textString));
+	}
+
+	public void setPreviousEncodingMemento(EncodingMemento previousEncodingMemento) {
+		fPreviousEncodingMemento = previousEncodingMemento;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CommonCharsetNames.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CommonCharsetNames.java
new file mode 100644
index 0000000..b563a28
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CommonCharsetNames.java
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2011 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.Properties;
+import java.util.PropertyResourceBundle;
+import java.util.ResourceBundle;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.sse.core.internal.encoding.util.Logger;
+import org.osgi.framework.Bundle;
+
+/**
+ * CommonCharsets is a utility class to provide a central place to map some
+ * IANA charset name to a Java charset name. In 1.4 JRE's this mostly is a
+ * thin wrapper of existing Charset functionality. It does, however, allow
+ * some "overriding" of the built in JRE mappings in the event they are
+ * necessary. See CodedIO.checkMappingOverrides.
+ * <p>
+ * This class also provides some convenient human readable description for the
+ * charset names which can be used in user interfaces. The description is NL
+ * aware based on locale. The data is populated via the charset.properties
+ * file only once, based on static initialization of the hashtables.
+ * <p>
+ * The IANA tags are based on reference information found at the
+ * http://www.iana.org site. Specifically see
+ * http://www.iana.org/assignments/character-sets
+ */
+public final class CommonCharsetNames {
+
+	private static Properties defaultIANAmappings = null;
+
+	private static ArrayList encodings = null;
+
+	private static Hashtable supportedEncodingDisplayNames = null;
+
+	private static Map prefNames = null;
+
+	/**
+	 * Returns list of commonly available encoding names. Suitable for
+	 * populating a UI dialog or drop down. This list would be a subset of all
+	 * possible charsets the VM supports (which can get into the hundreds).
+	 * For the VM supported charsets, use
+	 * <code>Charset.availableCharsets()</code>
+	 * 
+	 * @return String[]
+	 */
+	public static String[] getCommonCharsetNames() {
+		String[] enc = new String[getEncodings().size()];
+		getEncodings().toArray(enc);
+		return enc;
+	}
+
+	/**
+	 * @return Returns the defaultIANAmappings.
+	 */
+	private static Properties getDefaultIANAMappings() {
+		if (defaultIANAmappings == null) {
+			defaultIANAmappings = new Properties();
+			Bundle keyBundle = Platform.getBundle(ICodedResourcePlugin.ID);
+			IPath keyPath = new Path("config/defaultIANA.properties"); //$NON-NLS-1$
+			URL location = Platform.find(keyBundle, keyPath);
+			InputStream propertiesInputStream = null;
+			try {
+				propertiesInputStream = location.openStream();
+				defaultIANAmappings.load(propertiesInputStream);
+			}
+			catch (IOException e) {
+				// if can't read, just assume there's no
+				// default IANA mappings
+				// and repeated attempts will not occur,
+				// since they
+				// will be represented by an empty
+				// Properties object
+			}
+		}
+		return defaultIANAmappings;
+	}
+
+	/**
+	 * Returns display (translated) string for encoding name. If there is no
+	 * "custom" translated version available, it defers to ther VM's Charset
+	 * support. It will return null if no display name is available.
+	 * 
+	 * @param String
+	 *            charset name
+	 * @return Human friendly display name
+	 */
+	public static String getDisplayString(String charsetName) {
+		if (charsetName == null)
+			return null;
+		String result = (String) getSupportedEncodingDisplayNames().get(charsetName);
+		if (result == null) {
+			// if we don't have a special one, just return
+			// what's provided by Charset
+
+			try {
+				Charset charset = Charset.forName(charsetName);
+				result = charset.displayName();
+			}
+			catch (UnsupportedCharsetException e) {
+				// if not supported, the display name is
+				// the least of clients concerns :)
+			}
+		}
+		return result;
+	}
+
+	public static String getPreferenceName(String charsetName) {
+		if (charsetName == null)
+			return null;
+
+		String result = (String) getPreferenceNames().get(charsetName);
+		if (result == null) {
+			return charsetName;
+		}
+
+		return result;
+	}
+	/**
+	 * @return Returns the javaEncodings.
+	 */
+	private static ArrayList getEncodings() {
+		if (encodings == null) {
+			initHashTables();
+		}
+		return encodings;
+	}
+
+	public static String getIanaPreferredCharsetName(String charsetName) {
+		String preferredName = charsetName;
+
+		try {
+			Charset charset = Charset.forName(charsetName);
+			if (charset.name() != null) {
+				preferredName = charset.name();
+			}
+		}
+		catch (IllegalCharsetNameException e) {
+			// just return input if illegal
+		}
+		catch (UnsupportedCharsetException e) {
+			// just return input if illegal
+		}
+		return preferredName;
+	}
+
+	/**
+	 * Returns a default IANA name that is listed in CommonCharsetNames. Here
+	 * is how it checks: 1. check to see if charsetName is in the
+	 * CommonCharsetNames list and if so, just return it. 2. check to see if
+	 * charsetName is listed in defaultIANAmappings which contains a mapping
+	 * of more common encodings and the default IANA name they should map to.
+	 * 3. return defaultIanaName if all else fails
+	 */
+	public static String getPreferredDefaultIanaName(String charsetName, String defaultIanaName) {
+		String preferredName = defaultIanaName;
+		String guessedName = charsetName;
+		try {
+			guessedName = CodedIO.getAppropriateJavaCharset(charsetName);
+		}
+		catch (IllegalCharsetNameException e) {
+			// just ignore if illegal
+		}
+		catch (UnsupportedCharsetException e) {
+			// just ignore if illegal
+		}
+		if (getEncodings().contains(guessedName))
+			preferredName = guessedName;
+		else {
+			preferredName = getDefaultIANAMappings().getProperty(guessedName, preferredName);
+		}
+
+		return preferredName;
+	}
+
+	/**
+	 * @return
+	 */
+	private static Hashtable getSupportedEncodingDisplayNames() {
+		if (supportedEncodingDisplayNames == null) {
+			initHashTables();
+		}
+		return supportedEncodingDisplayNames;
+	}
+
+	private static Map getPreferenceNames() {
+		if (prefNames == null) {
+			initHashTables();
+		}
+		return prefNames;
+	}
+
+	private static void initHashTables() {
+		if (supportedEncodingDisplayNames == null) {
+			// Initialize hash table for encoding table
+			supportedEncodingDisplayNames = new Hashtable();
+			encodings = new ArrayList();
+			prefNames = new HashMap();
+
+			ResourceBundle bundle = null;
+			InputStream bundleStream = null;
+			try {
+				URL bundleURL = Platform.find(Platform.getBundle(ICodedResourcePlugin.ID), Path.fromOSString("$nl$/config/charset.properties")); //$NON-NLS-1$
+				if (bundleURL != null) {
+					bundleStream = bundleURL.openStream();
+					bundle = new PropertyResourceBundle(bundleStream);
+				}
+
+				String totalNumString = bundle.getString("totalnumber");//$NON-NLS-1$
+				int totalNum = 0;
+				if (totalNumString.length() != 0) {
+					try {
+						totalNum = Integer.valueOf(totalNumString).intValue();
+					}
+					catch (NumberFormatException e) {
+						totalNum = 0;
+					}
+				}
+
+				for (int i = 0; i < totalNum; i++) {
+					String iana = bundle.getString("codeset." + i + ".iana");//$NON-NLS-2$//$NON-NLS-1$
+					String displayName = bundle.getString("codeset." + i + ".label");//$NON-NLS-2$//$NON-NLS-1$
+					String prefName = null;
+					try {
+						prefName = bundle.getString("codeset." + i + ".prefName"); //$NON-NLS-1$ //$NON-NLS-2$
+					}
+					catch (MissingResourceException e) {
+					}
+
+					encodings.add(iana);
+					supportedEncodingDisplayNames.put(iana, displayName);
+					if (prefName != null)
+						prefNames.put(prefName, iana);
+				}
+			}
+			catch (IOException e) {
+				Logger.logException("invalid install or configuration", e); //$NON-NLS-1$
+			}
+			finally {
+				try {
+					if (bundleStream != null)
+						bundleStream.close();
+				}
+				catch (IOException x) {
+				}
+			}
+		}
+	}
+
+	public static void main(String[] args) {
+		// unit test only
+		String test = "Cp1252"; //$NON-NLS-1$
+		String result = CommonCharsetNames.getIanaPreferredCharsetName(test);
+		System.out.println(test + " --> " + result); //$NON-NLS-1$
+
+		test = "MS932"; //$NON-NLS-1$
+		result = CommonCharsetNames.getIanaPreferredCharsetName(test);
+		System.out.println(test + " --> " + result); //$NON-NLS-1$
+
+	}
+
+	public CommonCharsetNames() {
+		super();
+		initHashTables();
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CommonEncodingPreferenceNames.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CommonEncodingPreferenceNames.java
new file mode 100644
index 0000000..087e03a
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/CommonEncodingPreferenceNames.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+/**
+ * Common preference keys used to specify encoding and end of line.
+ */
+public class CommonEncodingPreferenceNames {
+	
+	private CommonEncodingPreferenceNames() {
+		// empty private constructor so users cannot instantiate class
+	}
+
+	/**
+	 * Constant to be used when referring to CR/MAC line delimiter
+	 * @deprecated - no longer used
+	 */
+	public static final String CR = "EOL_Mac"; //$NON-NLS-1$
+	/**
+	 * Constant to be used when referring to CRLF/WINDOWS line delimiter
+	 * @deprecated - no longer used
+	 */
+	public static final String CRLF = "EOL_Windows"; //$NON-NLS-1$
+	/**
+	 * The end-of-line character(s) to use.
+	 * @deprecated - no longer used
+	 */
+	public static final String END_OF_LINE_CODE = "endOfLineCode";//$NON-NLS-1$
+	/**
+	 * The character code to use when reading a file.
+	 */
+	public static final String INPUT_CODESET = "inputCodeset";//$NON-NLS-1$
+
+	/**
+	 * Constant to be used when referring to LF/UNIX line delimiter
+	 * @deprecated - no longer used
+	 */
+	public static final String LF = "EOL_Unix"; //$NON-NLS-1$
+	/**
+	 * Constant to be used when referring to No translation of line delimiters
+	 * @deprecated - no longer used
+	 */
+	public static final String NO_TRANSLATION = ""; //$NON-NLS-1$
+	/**
+	 * The character code to use when writing a file.
+	 */
+	public static final String OUTPUT_CODESET = "outputCodeset";//$NON-NLS-1$
+
+	/**
+	 * String representation of CR/MAC line delimiter
+	 * @deprecated - no longer used
+	 */
+	public static final String STRING_CR = "\r";//$NON-NLS-1$
+
+	/**
+	 * String representation of CRLF/WINDOWS line delimiter
+	 * @deprecated - no longer used
+	 */
+	public static final String STRING_CRLF = "\r\n";//$NON-NLS-1$
+
+	/**
+	 * String representation of LF/UNIX line delimiter
+	 * @deprecated - no longer used
+	 */
+	public static final String STRING_LF = "\n";//$NON-NLS-1$
+
+	/**
+	 * String Use 3 byte BOM (Byte Order Mark) when saving UTF-8 encoded files
+	 */
+	public static final String USE_3BYTE_BOM_WITH_UTF8 = "Use3ByteBOMWithUTF8"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/ContentBasedPreferenceGateway.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/ContentBasedPreferenceGateway.java
new file mode 100644
index 0000000..cd28db3
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/ContentBasedPreferenceGateway.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.osgi.framework.Bundle;
+import org.osgi.service.prefs.Preferences;
+
+
+public class ContentBasedPreferenceGateway {
+	private static String DEFAULT_LOCATION = "org.eclipse.wst.sse.core"; //$NON-NLS-1$
+	private static String RUNTIME_XML_ID = "org.eclipse.core.runtime.xml"; //$NON-NLS-1$
+	private static String SSE_XML_ID = "org.eclipse.wst.xml.core.xmlsource"; //$NON-NLS-1$
+
+	/**
+	 * @param pluginId
+	 * @return
+	 */
+	private static boolean bundleExists(String pluginId) {
+
+		// this just verifies there's really a plugin with this ID in "stack"
+		Bundle bundle = Platform.getBundle(pluginId);
+		return (!(bundle == null));
+	}
+
+	/**
+	 * @param contentType
+	 * @return
+	 */
+	private static String getContributorPluginId(IContentType contentType) {
+		// TODO: need to have registration info here, but for now, we'll use
+		// simple heuristic to cover the cases we know about.
+		String fullId = null;
+		if (contentType == null) {
+			fullId = DEFAULT_LOCATION;
+		} else {
+			fullId = contentType.getId();
+		}
+		// only one known case, so far, of hard coded re-direction
+		// (not sure this is even needed, but just in case).
+		// We don't want to store/change runtime.xml preferences
+		if (RUNTIME_XML_ID.equals(fullId)) {
+			fullId = SSE_XML_ID;
+		}
+		String pluginId = inferPluginId(fullId);
+		return pluginId;
+	}
+
+	private static Preferences getDefaultPreferences(IContentType contentType) {
+		IEclipsePreferences eclipsePreferences = Platform.getPreferencesService().getRootNode();
+		// TODO: eventaully need extension mechanism to avoid these hard coded
+		// mechanism.
+		// The idea is to load/store based on plugin's preferences, where the
+		// content type was contributed
+		// Eventually, too, we could do more "dynamic lookup" to get parent
+		// types for defaults, etc.
+
+		// Get default plugin preferences
+		String pluginPreferenceLocation = DefaultScope.SCOPE + IPath.SEPARATOR + getContributorPluginId(contentType);
+		Preferences pluginPreferences = eclipsePreferences.node(pluginPreferenceLocation);
+
+		// the below code does not work at this time because content type
+		// preferences are stored in the place as plugin preferences
+
+		//		Preferences contentPreferences = null;
+		//		if (contentType != null) {
+		//			contentPreferences = pluginPreferences.node(contentType.getId());
+		//		}
+		//		else {
+		//			contentPreferences = pluginPreferences.node(DEFAULT_LOCATION );
+		//		}
+		//
+		//		return contentPreferences;
+
+		return pluginPreferences;
+
+	}
+
+	private static Preferences getDefaultPreferences(String contentTypeId) {
+		IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeId);
+		return getDefaultPreferences(contentType);
+	}
+
+	public static Preferences getPreferences(IContentType contentType) {
+		IEclipsePreferences eclipsePreferences = Platform.getPreferencesService().getRootNode();
+		// TODO: eventaully need extension mechanism to avoid these hard coded
+		// mechanism.
+		// The idea is to load/store based on plugin's preferences, where the
+		// content type was contributed
+		// Eventually, too, we could do more "dynamic lookup" to get parent
+		// types for defaults, etc.
+
+		// Get instance plugin preferences
+		String pluginPreferenceLocation = Plugin.PLUGIN_PREFERENCE_SCOPE + IPath.SEPARATOR + getContributorPluginId(contentType);
+		Preferences pluginPreferences = eclipsePreferences.node(pluginPreferenceLocation);
+
+		// the below code does not work at this time because content type
+		// preferences are stored in the place as plugin preferences
+
+		//		Preferences contentPreferences = null;
+		//		if (contentType != null) {
+		//			contentPreferences = pluginPreferences.node(contentType.getId());
+		//		}
+		//		else {
+		//			contentPreferences = pluginPreferences.node(DEFAULT_LOCATION );
+		//		}
+		//
+		//		return contentPreferences;
+		return pluginPreferences;
+
+	}
+
+	public static Preferences getPreferences(String contentTypeId) {
+		IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeId);
+		return getPreferences(contentType);
+	}
+
+	public static String getPreferencesString(IContentType contentType, String key) {
+		Preferences preferences = getPreferences(contentType);
+		String value = preferences.get(key, getDefaultPreferences(contentType).get(key, null));
+		return value;
+	}
+
+	public static String getPreferencesString(String contentTypeId, String key) {
+		Preferences preferences = getPreferences(contentTypeId);
+		String value = preferences.get(key, getDefaultPreferences(contentTypeId).get(key, null));
+		return value;
+	}
+
+	/**
+	 * @param fullId
+	 * @return
+	 */
+	private static String inferPluginId(String fullId) {
+		// simply trim off last "segment" from full ID.
+		int lastSegmentPos = fullId.lastIndexOf('.');
+		String pluginId = null;
+		if (lastSegmentPos != -1) {
+			pluginId = fullId.substring(0, lastSegmentPos);
+		} else {
+			// weird case? We'll at least put/get them somewhere
+			pluginId = DEFAULT_LOCATION;
+		}
+		if (!bundleExists(pluginId)) {
+			// use default location
+			pluginId = DEFAULT_LOCATION;
+		}
+		return pluginId;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/ContentTypeEncodingPreferences.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/ContentTypeEncodingPreferences.java
new file mode 100644
index 0000000..4c82676
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/ContentTypeEncodingPreferences.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.wst.sse.core.internal.encoding.util.Assert;
+
+
+/**
+ * A convenience class to statically get preferenences.
+ */
+
+public abstract class ContentTypeEncodingPreferences {
+
+	// actually a null/empty string also means use workbench default so this
+	// constant might not really be necessary
+	public static final String WORKBENCH_DEFAULT = "WORKBENCH_DEFAULT"; //$NON-NLS-1$
+
+
+	private static final String getJavaPlatformDefaultEncoding() {
+		// note: its important to use this system property,
+		// instead
+		// of
+		// ByteToCharConverter.getDefault().getCharacterEncoding()
+		// inorder to handle changes "on the fly". the
+		// ByteToCharConverter
+		// default is apparently set only when VM starts.
+		// There's not really any "cusomter scnererios"
+		// that change the
+		// default encoding "on the fly", but its at least
+		// used during
+		// our automated tests.
+		String enc = System.getProperty("file.encoding"); //$NON-NLS-1$
+		// return blank as null
+		if (enc != null && enc.trim().length() == 0) {
+			enc = null;
+		}
+		return enc;
+	}
+
+
+	public static final String getPreferredNewLineDelimiter(String contentTypeId) {
+		String result = null;
+		String newLineCode = null;
+		newLineCode = ContentBasedPreferenceGateway.getPreferencesString(contentTypeId, CommonEncodingPreferenceNames.END_OF_LINE_CODE);
+		if (newLineCode == null)
+			result = null;
+		else if (newLineCode.equals(CommonEncodingPreferenceNames.CR))
+			result = CommonEncodingPreferenceNames.STRING_CR;
+		else if (newLineCode.equals(CommonEncodingPreferenceNames.LF))
+			result = CommonEncodingPreferenceNames.STRING_LF;
+		else if (newLineCode.equals(CommonEncodingPreferenceNames.CRLF))
+			result = CommonEncodingPreferenceNames.STRING_CRLF;
+		return result;
+	}
+
+	/**
+	 * Returns current output encoding preference for contentTypeIdentifier
+	 * (unique IANA encoding)
+	 */
+	public static final String getUserPreferredCharsetName(String contentTypeId) {
+		String prefEncoding = ContentBasedPreferenceGateway.getPreferencesString(contentTypeId, CommonEncodingPreferenceNames.OUTPUT_CODESET);
+		String encoding = prefEncoding;
+		// get workbench encoding preference if preference
+		// requests it
+		if (prefEncoding == null || prefEncoding.trim().length() == 0 || prefEncoding.equals(ContentTypeEncodingPreferences.WORKBENCH_DEFAULT)) {
+			encoding = ContentTypeEncodingPreferences.getWorkbenchPreferredCharsetName();
+		}
+		return encoding;
+	}
+
+	/**
+	 * Utility method to get specified preference. Subclasses can't override,
+	 * since we expect this to work in a consistent way. Note: this is
+	 * specific to HTML and CSS and is intended to supply a "default spec"
+	 * other than the workbench platform's default, only for those cases where
+	 * there is no encoding specified anywhere else, e.g. in the file, or as a
+	 * file or folder property.
+	 */
+	public static final String getUserSpecifiedDefaultEncodingPreference() {
+		String ContentTypeID_HTML = "org.eclipse.wst.html.core.htmlsource"; //$NON-NLS-1$
+		return getUserSpecifiedDefaultEncodingPreference(ContentTypeID_HTML);
+	}
+
+	public static final String getUserSpecifiedDefaultEncodingPreference(String contentTypeID) {
+		String enc = null;
+
+		// first try to get base's default encoding for content type
+		IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeID);
+		if (contentType != null) {
+			enc = contentType.getDefaultCharset();
+		}
+		
+		// next try to get sse's default encoding for content type
+		if (enc == null || enc.trim().length() == 0) {
+			enc = ContentBasedPreferenceGateway.getPreferencesString(contentTypeID, CommonEncodingPreferenceNames.INPUT_CODESET);
+		}
+		
+		// next, just try and use workbench encoding
+		if (enc == null || enc.trim().length() == 0) {
+			enc = getWorkbenchSpecifiedDefaultEncoding();
+		}
+		
+		// return blank as null
+		if (enc != null && enc.trim().length() == 0) {
+			enc = null;
+		}
+		return enc;
+	}
+
+	/**
+	 * Returns Workbench encoding preference. Note: if workbench encoding is
+	 * null, platform encoding will be returned.
+	 */
+	private static final String getWorkbenchPreferredCharsetName() {
+		String charset = ResourcesPlugin.getEncoding();
+		charset = CommonCharsetNames.getIanaPreferredCharsetName(charset);
+		return charset;
+	}
+
+	/**
+	 * Returns Workbench encoding preference. Will return null if none
+	 * specified.
+	 */
+	private static final String getWorkbenchSpecifiedDefaultEncoding() {
+		ResourcesPlugin resourcePlugin = ResourcesPlugin.getPlugin();
+		String enc = resourcePlugin.getPluginPreferences().getString(ResourcesPlugin.PREF_ENCODING);
+		// return blank as null
+		if (enc != null && enc.trim().length() == 0) {
+			enc = null;
+		}
+		return enc;
+	}
+
+	public static final String useDefaultNameRules(IResourceCharsetDetector encodingProvider) {
+		String result = null;
+		String enc = null;
+		enc = encodingProvider.getSpecDefaultEncoding();
+		if (enc != null) {
+			result = enc;
+		} else {
+			enc = getUserSpecifiedDefaultEncodingPreference();
+			if (enc != null && enc.trim().length() > 0) {
+				result = enc;
+			} else {
+				if (enc == null || enc.trim().length() == 0) {
+					enc = getWorkbenchSpecifiedDefaultEncoding();
+					if (enc != null) {
+						result = enc;
+					}
+				}
+				if (enc == null || enc.trim().length() == 0) {
+					enc = getJavaPlatformDefaultEncoding();
+					// enc should never be null (but we'll
+					// check anyway)
+					if (enc != null) {
+						result = enc;
+					}
+				}
+			}
+		}
+		Assert.isNotNull(enc, "post condition invalid"); //$NON-NLS-1$
+		result = CodedIO.checkMappingOverrides(enc);
+		return result;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/EncodingMemento.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/EncodingMemento.java
new file mode 100644
index 0000000..c195a84
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/EncodingMemento.java
@@ -0,0 +1,247 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+import org.eclipse.core.runtime.content.IContentDescription;
+
+
+/**
+ * This class is to simply hold information and data about the type of
+ * encoding found for a resource. It not only includes names, etc., but also
+ * gives hints about the algorithm, or rule, that the encodng was determined.
+ * Having all this info in a central object, associated with the Document
+ * (technically, IStructuredDocument), allows for better user error messages,
+ * and better handling of knowing how to dump a file, given we know how it was
+ * loaded.
+ * 
+ * Note: the data in this class is only valid if its has actually gone through
+ * the loading or dumping sequence. It is not accurate, for example, if a
+ * structuredDocument is simply created and then setText called. In this type
+ * of case, accuracy for loading and dumping is not required, since its all
+ * re-discovered. One limitation is that structuredDocument's created "from
+ * scratch" this way, don't have any encoding information to count on, and
+ * would have to arrange the processing to be done. (And it is done,
+ * automatically if going through loader or dumper, but perhaps not in future
+ * new uses. TODO: this can be inproved in future versions.)
+ * 
+ * isInitialized is set when the loader or dumper processes have been used,
+ * but even this can't be counted on 100% if the document has been modified
+ * since.
+ * 
+ */
+public class EncodingMemento implements Cloneable {
+
+	public final static String CLONED = "cloned"; //$NON-NLS-1$
+	public final static String DEFAULTS_ASSUMED_FOR_EMPTY_INPUT = "DefaultsAssumedForEmptyInput"; //$NON-NLS-1$
+	public final static String DEFAULTS_USED_DUE_TO_SMALL_STREAM = "defaultsUsedDueToSmallStream"; //$NON-NLS-1$
+
+
+	/*
+	 * Strings to be used for tracing. TODO: need to clean this up, we no
+	 * longer use all of them
+	 */
+	public final static String DETECTED_STANDARD_UNICODE_BYTES = "detectedStandardUnicodeBytes"; //$NON-NLS-1$
+	public final static String FOUND_ENCODING_IN_CONTENT = "foundEncodingInContent"; //$NON-NLS-1$
+	public final static String FOUND_ENCODING_IN_STREAM = "foundEncodingInStream"; //$NON-NLS-1$
+	public final static String FOUND_ENCODING_IN_STRUCTURED_DOCUMENT = "foundEncodingInStructuredDocument"; //$NON-NLS-1$
+	public final static String GUESSED_ENCODING_FROM_STREAM = "GuessEncodingFromStream"; //$NON-NLS-1$
+	public final static String JAVA_NAME_FOUND_AS_IANA_NAME = "noMappingFoundButJavaNameFoundToBeIANAName"; //$NON-NLS-1$
+	public final static String JAVA_NAME_FOUND_IN_ALIAS_NAME = "noMappingFoundButJavaNameFoundInAliasTable"; //$NON-NLS-1$
+	public final static String NO_IANA_NAME_FOUND = "noMappingFoundFromJavaNameToIANAName"; //$NON-NLS-1$
+	public final static String USED_CONTENT_TYPE_DEFAULT = "UsedContentTypeDefault"; //$NON-NLS-1$
+	public final static String USED_JAVA_DEFAULT = "UsedJavaDefault"; //$NON-NLS-1$
+	public final static String USED_MEMENTO_FROM_LOAD = "usedMementoFromLoad"; //$NON-NLS-1$
+	public final static String USED_PROPERTY_SETTINGS = "USED_PROPERTY_SETTINGS"; //$NON-NLS-1$
+	public final static String USED_USER_SPECIFIED_PREFERENCE = "UsedUserSpecifiedPreference"; //$NON-NLS-1$
+	public final static String USED_WORKSPACE_DEFAULT = "UsedWorkspaceDefault"; //$NON-NLS-1$
+	public final static String USER_IS_USING_JAVA_ENCODING = "UserIsUsingJavaEncoding"; //$NON-NLS-1$
+	private String fAppropriateDefault;
+	private String fDetectedCharsetName;
+	private String fInvalidEncoding;
+
+
+	private String fJavaCharsetName;
+	private boolean fUnicodeStream;
+	private boolean fUTF83ByteBOMUsed;
+	
+	private byte[] fBOM;
+
+	public EncodingMemento() {
+		super();
+	}
+
+	/**
+	 * Returns a clone of this object.
+	 */
+	public Object clone() {
+		EncodingMemento object = null;
+		try {
+			object = (EncodingMemento) super.clone();
+		}
+		catch (CloneNotSupportedException e) {
+			// impossible, since we're implementing here
+		}
+
+		return object;
+
+	}
+
+	/**
+	 * Returns the appropriateDefault. This is only set if an invalid encoding
+	 * was found, and contains an charset appropriate to use as a default
+	 * value, if, for example, the user decides to load the document anyway,
+	 * even though the charset was found to be invalid.
+	 * 
+	 * @return String
+	 */
+	public String getAppropriateDefault() {
+		if (fAppropriateDefault == null) {
+			fAppropriateDefault = NonContentBasedEncodingRules.useDefaultNameRules(null);
+		}
+		return fAppropriateDefault;
+	}
+
+	/**
+	 * Returns the charset name, if it is different from the charset name
+	 * found in getJavaCharsetName. This can happen, for example, if there are
+	 * differences in case. This method might return SHIFT_JIS, and the the
+	 * getJavaCharsetName might return Shift_JIS -- if SHIFT_JIS was detected
+	 * in file/document. If the original file contained the correct case, then
+	 * this method would return null. The getJavaCharsetName is typically the
+	 * one that should always be used, and this one only used for certain
+	 * error conditions, or or if when creating a "duplicate" resource, it was
+	 * desired to use exactly the charset name as in the original document. As
+	 * an example of this later case, the original document might contain
+	 * ISO-8859-9, but the detected charset name might contain ISO-8859-9-I.
+	 * 
+	 * @return String
+	 */
+	public String getDetectedCharsetName() {
+		return fDetectedCharsetName;
+	}
+
+	/**
+	 * Returns a charset name that was detected, but not found to be a charset
+	 * suppoorted by the VM.
+	 * 
+	 * @return String
+	 */
+	public String getInvalidEncoding() {
+		return fInvalidEncoding;
+	}
+
+	/**
+	 * Returns the java cononical charset name.
+	 * 
+	 * @return String
+	 */
+	public String getJavaCharsetName() {
+		return fJavaCharsetName;
+	}
+
+	/**
+	 * Note: we may be able to remove this method, if it turns out this work
+	 * is done by "text" type.
+	 * 
+	 * @deprecated -
+	 */
+	public byte[] getUnicodeBOM() {
+		byte[] bom = null;
+		if (isUTF83ByteBOMUsed())
+			bom = IContentDescription.BOM_UTF_8;
+		else if (isUnicodeStream())
+			bom = fBOM;
+		return bom;
+	}
+
+	/**
+	 * Note: in our implementation, the stream is a unicode stream if the
+	 * charset is UTF-16, UTF-16LE, or UTF-16BE. A stream with 3 byte BOM is
+	 * not considered unicode stream here.
+	 * 
+	 * @return returns true if is a unicode (UTF-16) stream
+	 */
+	public boolean isUnicodeStream() {
+		return fUnicodeStream;
+	}
+
+	/**
+	 * Note: in our implementation, the stream is a unicode stream if the
+	 * charset is UTF-16, UTF-16LE, or UTF-16BE. A stream with 3 byte BOM is
+	 * not considered unicode stream here.
+	 * 
+	 * Set during load, can be used by dumper to write 3 byte BOM, which Java
+	 * does not normally do. This helps maintain compatibility with other
+	 * programs (those that wrote the 3 byte BOM there to begin with.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isUTF83ByteBOMUsed() {
+		return fUTF83ByteBOMUsed;
+	}
+
+	public boolean isValid() {
+		return getInvalidEncoding() == null;
+	}
+
+	/**
+	 * Sets the appropriateDefault.
+	 * 
+	 * @param appropriateDefault
+	 *            The appropriateDefault to set
+	 */
+	public void setAppropriateDefault(String appropriateDefault) {
+		fAppropriateDefault = appropriateDefault;
+	}
+
+
+	public void setDetectedCharsetName(String detectedCharsetName) {
+		fDetectedCharsetName = detectedCharsetName;
+	}
+
+	public void setInvalidEncoding(String invalidEncoding) {
+		fInvalidEncoding = invalidEncoding;
+	}
+
+	/**
+	 * Sets the javaEncodingName.
+	 * 
+	 * @param javaEncodingName
+	 *            The javaEncodingName to set
+	 */
+	public void setJavaCharsetName(String javaCharsetName) {
+		fJavaCharsetName = javaCharsetName;
+	}
+
+	/**
+	 * @param b
+	 */
+	public void setUnicodeStream(boolean unicodeStream) {
+		fUnicodeStream = unicodeStream;
+
+	}
+
+	/**
+	 * Sets the uTF83ByteBOMfound.
+	 * 
+	 * @param uTF83ByteBOMfound
+	 *            The uTF83ByteBOMfound to set
+	 */
+	public void setUTF83ByteBOMUsed(boolean uTF83ByteBOMUsed) {
+		fUTF83ByteBOMUsed = uTF83ByteBOMUsed;
+	}
+
+	public void setUnicodeBOM(byte[] bom) {
+		fBOM = bom;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/EncodingRule.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/EncodingRule.java
new file mode 100644
index 0000000..2d2988f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/EncodingRule.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+
+/**
+ * Class to provided "enumerated types" for encoding rule parameter. This is
+ * to be used by client to have some control over how encoding is determined.
+ */
+public class EncodingRule {
+	/**
+	 * CONTENT_BASED means the class which uses the parameter (such as
+	 * contentType Loaders) should use what ever rules it normally would.
+	 * (Note, some content type loaders may not always literally use the file
+	 * content to determine encoding, but the point is they should use what
+	 * ever rules they normally would.)
+	 */
+	public static final EncodingRule CONTENT_BASED = new EncodingRule("CONTENT_BASED"); //$NON-NLS-1$
+	/**
+	 * FORCE_DEFAULT means the class which uses the parameter (such as
+	 * contentType Loaders) should use what ever it defines as the default
+	 * encoding.
+	 */
+	public static final EncodingRule FORCE_DEFAULT = new EncodingRule("FORCE_DEFAULT"); //$NON-NLS-1$
+
+	/**
+	 * IGNORE_CONVERSION_ERROR means that the save operation should save even
+	 * if it encounters conversion errors. This will result in some data loss,
+	 * so should only be used after the user confirms that is indeed what they
+	 * want to do.
+	 */
+	public static final EncodingRule IGNORE_CONVERSION_ERROR = new EncodingRule("IGNORE_CONVERSION_ERROR"); //$NON-NLS-1$
+
+
+	private final String encodingRule;
+
+	/**
+	 * Constructor for EncodingRule is private, so no one can instantiate
+	 * except this class itself.
+	 */
+	private EncodingRule(String ruleName) {
+		super();
+		encodingRule = ruleName;
+	}
+
+	public String toString() {
+		return encodingRule;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/ICodedResourcePlugin.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/ICodedResourcePlugin.java
new file mode 100644
index 0000000..4b4900f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/ICodedResourcePlugin.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+
+public interface ICodedResourcePlugin {
+	String ID = "org.eclipse.wst.sse.core"; //$NON-NLS-1$
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/IContentDescriptionExtended.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/IContentDescriptionExtended.java
new file mode 100644
index 0000000..db2e0a4
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/IContentDescriptionExtended.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+import org.eclipse.core.runtime.QualifiedName;
+
+
+public interface IContentDescriptionExtended {
+	/**
+	 * The APPROPRIATE_DEFAULT field is used only when the
+	 * IContentType.getDefaultCharset returns null. Its typically set from
+	 * user preferences. Known uses cases are HTML and CSS, where there is no
+	 * "spec default" for those content types.
+	 */
+	public static final QualifiedName APPROPRIATE_DEFAULT = new QualifiedName(ICodedResourcePlugin.ID, "appropriateDefault"); //$NON-NLS-1$
+	/**
+	 * The DETECTED_CHARSET property should be set when the "detected" charset
+	 * is different from the java charset, even though functionally
+	 * equivelent. This can occur, for example, when the cases are different,
+	 * or when an alias name is used instead of the conanical name.
+	 */
+	public final static QualifiedName DETECTED_CHARSET = new QualifiedName(ICodedResourcePlugin.ID, "detectedCharset"); //$NON-NLS-1$
+	/**
+	 * The UNSUPPORTED_CHARSET property holds the charset value, if its been
+	 * found to be an unsuppoted charset. This is helpful in error messages,
+	 * or in cases when even though the charset is invalid, the java charset
+	 * is assumed to be the default.
+	 */
+	public final static QualifiedName UNSUPPORTED_CHARSET = new QualifiedName(ICodedResourcePlugin.ID, "unsupportedCharset"); //$NON-NLS-1$
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/IResourceCharsetDetector.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/IResourceCharsetDetector.java
new file mode 100644
index 0000000..20dcbbf
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/IResourceCharsetDetector.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+
+public interface IResourceCharsetDetector extends IStreamCharsetDetector {
+	void set(IStorage iStorage) throws CoreException;
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/IStreamCharsetDetector.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/IStreamCharsetDetector.java
new file mode 100644
index 0000000..a2508f1
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/IStreamCharsetDetector.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+public interface IStreamCharsetDetector {
+	String getEncoding() throws IOException;
+
+	String getSpecDefaultEncoding();
+
+	void set(InputStream inputStream);
+
+	void set(Reader reader);
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/NonContentBasedEncodingRules.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/NonContentBasedEncodingRules.java
new file mode 100644
index 0000000..dd7158d
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/NonContentBasedEncodingRules.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentType;
+
+public class NonContentBasedEncodingRules {
+
+	private static final String getJavaPlatformDefaultEncoding() {
+		String enc = System.getProperty("file.encoding"); //$NON-NLS-1$
+		// return blank as null
+		if (enc != null && enc.trim().length() == 0) {
+			enc = null;
+		}
+		return enc;
+	}
+
+
+	public static String getUserSpecifiedDefaultForContentType(IFile iFile) {
+		String enc = null;
+		
+		IContentType contentType = null;
+		try {
+			contentType = iFile.getContentDescription().getContentType();
+			
+			// first try to get base's default encoding for content type 
+			if (contentType != null) {
+				enc = contentType.getDefaultCharset();
+			}
+
+			// next try to get sse's default encoding for content type
+			if (enc == null || enc.trim().length() == 0) {
+				enc = ContentBasedPreferenceGateway.getPreferencesString(contentType, CommonEncodingPreferenceNames.INPUT_CODESET);
+			}
+			
+			// return blank as null
+			if (enc != null && enc.trim().length() == 0) {
+				enc = null;
+			}
+		} catch (CoreException e) {
+			// if core exception occurs, assume no preference!
+			enc = null;
+		}
+		return enc;
+	}
+
+	public static String getUserSpecifiedDefaultForContentType(String contentTypeId) {
+		String enc = null;
+		
+		// first try to get base's default encoding for content type
+		IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeId);
+		if (contentType != null) {
+			enc = contentType.getDefaultCharset();
+		}
+		
+		// next try to get sse's default encoding for content type
+		if (enc == null || enc.trim().length() == 0) {
+			enc = ContentBasedPreferenceGateway.getPreferencesString(contentTypeId, CommonEncodingPreferenceNames.INPUT_CODESET);
+		}
+		
+		// return blank as null
+		if (enc != null && enc.trim().length() == 0) {
+			enc = null;
+		}
+		return enc;
+	}
+
+	private static final String getWorkbenchSpecifiedDefaultEncoding() {
+		ResourcesPlugin resourcePlugin = ResourcesPlugin.getPlugin();
+		String enc = resourcePlugin.getPluginPreferences().getString(ResourcesPlugin.PREF_ENCODING);
+		// return blank as null
+		if (enc != null && enc.trim().length() == 0) {
+			enc = null;
+		}
+		return enc;
+	}
+
+	/**
+	 * @param specDefault
+	 *            This is the default charset name that would ordinarily be
+	 *            used for a particular type of content. Null may be
+	 *            specififed for those types with no spec default. If the spec
+	 *            default is known (and passed in), then it will be returned
+	 *            after being checked to see if there's be any user specified
+	 *            "override" for that charset (which would be rare). In other
+	 *            words, if the spec is known, there's little reason to use
+	 *            this method.
+	 * @return the charset that should be used according to the rules
+	 *         established by this class.
+	 */
+	public static final String useDefaultNameRules(String specDefault) {
+		String enc = null;
+		String result = null;
+		enc = specDefault;
+		if (enc != null) {
+			result = enc;
+		} else {
+			enc = ContentTypeEncodingPreferences.getUserSpecifiedDefaultEncodingPreference();
+			if (enc != null && enc.trim().length() > 0) {
+				result = enc.trim();
+			} else {
+				if (enc == null || enc.trim().length() == 0) {
+					enc = getWorkbenchSpecifiedDefaultEncoding();
+					if (enc != null) {
+						result = enc.trim();
+					}
+				}
+				if (enc == null || enc.trim().length() == 0) {
+					enc = getJavaPlatformDefaultEncoding();
+					// enc should never be null (but we'll
+					// check anyway)
+					if (enc != null) {
+						result = enc;
+					}
+				}
+			}
+		}
+		result = CodedIO.checkMappingOverrides(result);
+		return result;
+	}
+
+	private NonContentBasedEncodingRules() {
+		super();
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/Assert.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/Assert.java
new file mode 100644
index 0000000..4e1b370
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/Assert.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding.util;
+
+/**
+ * <code>Assert</code> is useful for for embedding runtime sanity checks in
+ * code. The predicate methods all test a condition and throw some type of
+ * unchecked exception if the condition does not hold.
+ * <p>
+ * Assertion failure exceptions, like most runtime exceptions, are thrown when
+ * something is misbehaving. Assertion failures are invariably unspecified
+ * behavior; consequently, clients should never rely on these being thrown
+ * (and certainly should not being catching them specifically).
+ * </p>
+ */
+public final class Assert {
+
+	/**
+	 * <code>AssertionFailedException</code> is a runtime exception thrown
+	 * by some of the methods in <code>Assert</code>.
+	 * <p>
+	 * This class is not declared public to prevent some misuses; programs
+	 * that catch or otherwise depend on assertion failures are susceptible to
+	 * unexpected breakage when assertions in the code are added or removed.
+	 * </p>
+	 */
+	static class AssertionFailedException extends RuntimeException {
+		/**
+		 * Comment for <code>serialVersionUID</code>
+		 */
+		private static final long serialVersionUID = 1L;
+
+		/**
+		 * Constructs a new exception.
+		 */
+		public AssertionFailedException() {
+			super();
+		}
+
+		/**
+		 * Constructs a new exception with the given message.
+		 */
+		public AssertionFailedException(String detail) {
+			super(detail);
+		}
+	}
+
+	/**
+	 * Asserts that an argument is legal. If the given boolean is not
+	 * <code>true</code>, an <code>IllegalArgumentException</code> is
+	 * thrown. The given message is included in that exception, to aid
+	 * debugging.
+	 * 
+	 * @param expression
+	 *            the outcode of the check
+	 * @param message
+	 *            the message to include in the exception
+	 * @return <code>true</code> if the check passes (does not return if the
+	 *         check fails)
+	 * @exception IllegalArgumentException
+	 *                if the legality test failed
+	 */
+	public static boolean isLegal(boolean expression, String message) {
+		if (!expression)
+			throw new AssertionFailedException(message);
+		return expression;
+	}
+
+	/**
+	 * Asserts that the given object is not <code>null</code>. If this is
+	 * not the case, some kind of unchecked exception is thrown. The given
+	 * message is included in that exception, to aid debugging.
+	 * 
+	 * @param object
+	 *            the value to test
+	 * @param message
+	 *            the message to include in the exception
+	 * @exception IllegalArgumentException
+	 *                if the object is <code>null</code>
+	 */
+	public static void isNotNull(Object object, String message) {
+		if (object == null) {
+			throw new AssertionFailedException();
+		}
+	}
+
+	/**
+	 * Asserts that the given boolean is <code>true</code>. If this is not
+	 * the case, some kind of unchecked exception is thrown. The given message
+	 * is included in that exception, to aid debugging.
+	 * 
+	 * @param expression
+	 *            the outcode of the check
+	 * @param message
+	 *            the message to include in the exception
+	 * @return <code>true</code> if the check passes (does not return if the
+	 *         check fails)
+	 */
+	public static boolean isTrue(boolean expression, String message) {
+		if (!expression) {
+			throw new AssertionFailedException();
+		}
+		return expression;
+	}
+
+	/* This class is not intended to be instantiated. */
+	private Assert() {
+		super();
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/BufferedLimitedReader.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/BufferedLimitedReader.java
new file mode 100644
index 0000000..f026bda
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/BufferedLimitedReader.java
@@ -0,0 +1,58 @@
+package org.eclipse.wst.sse.core.internal.encoding.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * This is a pretty limited implementation, sort of specific 
+ * to the way its used by tokenizers (JFlex). To really 
+ * be general purpose, would need more work. 
+ *
+ */
+
+
+public class BufferedLimitedReader extends BufferedReader {
+	private int limitedCount;
+	private int nRead;
+
+	public BufferedLimitedReader(Reader reader, int size) {
+		super(reader, size);
+		if (reader.markSupported()) {
+			try {
+				mark(size);
+			}
+			catch (IOException e) {
+				// impossible
+				e.printStackTrace();
+			}
+		}
+		limitedCount = size;
+	}
+
+	public int read() throws IOException {
+		int result = 0;
+		nRead++;
+		if (nRead > limitedCount) {
+			result = -1;
+		}
+		else {
+			result = super.read();
+		}
+		return result;
+
+	}
+
+	public int read(char cbuf[], int off, int len) throws IOException {
+		int result = 0;
+		if (nRead + len > limitedCount) {
+			result = -1;
+		}
+		else {
+			result = super.read(cbuf, off, len);
+			nRead = nRead + result;
+		}
+		return result;
+	}
+	
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/BufferedLimitedStream.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/BufferedLimitedStream.java
new file mode 100644
index 0000000..8928655
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/BufferedLimitedStream.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding.util;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class BufferedLimitedStream extends BufferedInputStream {
+
+	private int limitedCount;
+
+	public BufferedLimitedStream(InputStream inStream, int size) {
+		super(inStream, size);
+		mark(size);
+		try {
+			limitedCount = Math.min(size, inStream.available());
+		} catch (IOException e) {
+			// unlikely
+			limitedCount = 0;
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#available()
+	 */
+	public synchronized int available() throws IOException {
+
+		return limitedCount - pos;
+	}
+
+	/**
+	 * copied down from super class
+	 */
+	private void ensureOpen() throws IOException {
+		if (in == null)
+			throw new IOException("Stream closed"); //$NON-NLS-1$
+	}
+
+	/**
+	 * copied down from super class then, changed to simiulate EOF if goes
+	 * beyond buffered amount
+	 */
+	public synchronized int read() throws IOException {
+		ensureOpen();
+		// for this special stream, indicate "end of file" when buffer is
+		// full
+		if (pos >= limitedCount) {
+			return -1;
+		}
+		return super.read();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#read(byte[], int, int)
+	 */
+	public synchronized int read(byte[] b, int off, int len) throws IOException {
+		// for this special stream, indicate "end of file" when buffer is
+		// full
+		if (pos >= limitedCount) {
+			return -1;
+		}
+		return super.read(b, off, len);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/ByteReader.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/ByteReader.java
new file mode 100644
index 0000000..35046e2
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/ByteReader.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+
+/**
+ * This is an "adapter" class, simply to get in input stream to act like a
+ * reader. We could not use InputStreamReader directly because its internal
+ * buffers are not controllable, and it sometimes pulls too much out of input
+ * stream (even when it wasn't needed for our purposes).
+ * 
+ * The use of this class is highly specialized and by not means meant to be
+ * general purpose. Its use is restricted to those cases where the input
+ * stream can be regarded as ascii just long enough to determine what the real
+ * encoding should be.
+ */
+
+public class ByteReader extends Reader {
+
+	
+	public static final int DEFAULT_BUFFER_SIZE = CodedIO.MAX_BUF_SIZE;
+
+	protected byte[] fBuffer;
+
+	protected InputStream fInputStream;
+
+	protected ByteReader() {
+		super();
+	}
+
+	public ByteReader(InputStream inputStream) {
+		this(inputStream, DEFAULT_BUFFER_SIZE);
+		if (!inputStream.markSupported()) {
+			throw new IllegalArgumentException("ByteReader is required to have a resettable stream"); //$NON-NLS-1$
+		}
+	}
+
+	public ByteReader(InputStream inputStream, int size) {
+		this.fInputStream = inputStream;
+		if (!inputStream.markSupported()) {
+			throw new IllegalArgumentException("ByteReader is required to have a resettable stream"); //$NON-NLS-1$
+		}
+		this.fBuffer = new byte[size];
+
+	}
+
+	public void close() throws IOException {
+		this.fInputStream.close();
+	}
+
+	public void mark(int readAheadLimit) {
+		this.fInputStream.mark(readAheadLimit);
+	}
+
+	public boolean markSupported() {
+		return true;
+	}
+
+	public int read() throws IOException {
+		int b0 = this.fInputStream.read();
+		return (b0 & 0x00FF);
+	}
+
+	public int read(char ch[], int offset, int length) throws IOException {
+		if (length > this.fBuffer.length) {
+			length = this.fBuffer.length;
+		}
+
+		int count = this.fInputStream.read(this.fBuffer, 0, length);
+
+		for (int i = 0; i < count; i++) {
+			int b0 = this.fBuffer[i];
+			// the 0x00FF is to "lose" the negative bits filled in the byte to
+			// int conversion
+			// (and which would be there if cast directly from byte to char).
+			char c0 = (char) (b0 & 0x00FF);
+			ch[offset + i] = c0;
+		}
+		return count;
+	}
+
+	public boolean ready() throws IOException {
+		return this.fInputStream.available() > 0;
+	}
+
+	public void reset() throws IOException {
+		this.fInputStream.reset();
+	}
+
+	public long skip(long n) throws IOException {
+		return this.fInputStream.skip(n);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/CodedResourcePlugin.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/CodedResourcePlugin.java
new file mode 100644
index 0000000..0c928cd
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/CodedResourcePlugin.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding.util;
+
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.sse.core.internal.encoding.ICodedResourcePlugin;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class CodedResourcePlugin extends Plugin implements ICodedResourcePlugin {
+	//The shared instance.
+	private static CodedResourcePlugin plugin;
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static CodedResourcePlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns the workspace instance.
+	 */
+	public static IWorkspace getWorkspace() {
+		return ResourcesPlugin.getWorkspace();
+	}
+
+	/**
+	 * The constructor.
+	 */
+	public CodedResourcePlugin() {
+		super();
+		plugin = this;
+	}
+
+	protected void initializeDefaultPluginPreferences() {
+		Preferences prefs = getPluginPreferences();
+		prefs.setDefault(CommonEncodingPreferenceNames.USE_3BYTE_BOM_WITH_UTF8, false);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/Logger.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/Logger.java
new file mode 100644
index 0000000..9e911b9
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/Logger.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding.util;
+
+import com.ibm.icu.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.Bundle;
+
+
+/**
+ * Small convenience class to log messages to plugin's log file and also, if
+ * desired, the console. This class should only be used by classes in this
+ * plugin. Other plugins should make their own copy, with appropriate ID.
+ */
+public class Logger {
+	private static final String PLUGIN_ID = "org.eclipse.wst.sse.core.internal.encoding"; //$NON-NLS-1$
+	
+	public static final int ERROR = IStatus.ERROR; // 4
+	public static final int ERROR_DEBUG = 200 + ERROR;
+	public static final int INFO = IStatus.INFO; // 1
+	public static final int INFO_DEBUG = 200 + INFO;
+
+	public static final int OK = IStatus.OK; // 0
+
+	public static final int OK_DEBUG = 200 + OK;
+
+	private static final String TRACEFILTER_LOCATION = "/debug/tracefilter"; //$NON-NLS-1$
+	public static final int WARNING = IStatus.WARNING; // 2
+	public static final int WARNING_DEBUG = 200 + WARNING;
+
+	/**
+	 * Adds message to log.
+	 * 
+	 * @param level
+	 *            severity level of the message (OK, INFO, WARNING, ERROR,
+	 *            OK_DEBUG, INFO_DEBUG, WARNING_DEBUG, ERROR_DEBUG)
+	 * @param message
+	 *            text to add to the log
+	 * @param exception
+	 *            exception thrown
+	 */
+	protected static void _log(int level, String message, Throwable exception) {
+		if (level == OK_DEBUG || level == INFO_DEBUG || level == WARNING_DEBUG || level == ERROR_DEBUG) {
+			if (!isDebugging())
+				return;
+		}
+
+		int severity = IStatus.OK;
+		switch (level) {
+			case INFO_DEBUG :
+			case INFO :
+				severity = IStatus.INFO;
+				break;
+			case WARNING_DEBUG :
+			case WARNING :
+				severity = IStatus.WARNING;
+				break;
+			case ERROR_DEBUG :
+			case ERROR :
+				severity = IStatus.ERROR;
+		}
+		message = (message != null) ? message : "null"; //$NON-NLS-1$
+		Status statusObj = new Status(severity, PLUGIN_ID, severity, message, exception);
+		Bundle bundle = Platform.getBundle(PLUGIN_ID);
+		if (bundle != null) 
+			Platform.getLog(bundle).log(statusObj);
+	}
+
+	/**
+	 * Prints message to log if category matches /debug/tracefilter option.
+	 * 
+	 * @param message
+	 *            text to print
+	 * @param category
+	 *            category of the message, to be compared with
+	 *            /debug/tracefilter
+	 */
+	protected static void _trace(String category, String message, Throwable exception) {
+		if (isTracing(category)) {
+			message = (message != null) ? message : "null"; //$NON-NLS-1$
+			Status statusObj = new Status(IStatus.OK, PLUGIN_ID, IStatus.OK, message, exception);
+			Bundle bundle = Platform.getBundle(PLUGIN_ID);
+			if (bundle != null) 
+				Platform.getLog(bundle).log(statusObj);
+		}
+	}
+
+	/**
+	 * @return true if the platform is debugging
+	 */
+	public static boolean isDebugging() {
+		return Platform.inDebugMode();
+	}
+
+	/**
+	 * Determines if currently tracing a category
+	 * 
+	 * @param category
+	 * @return true if tracing category, false otherwise
+	 */
+	public static boolean isTracing(String category) {
+		if (!isDebugging())
+			return false;
+
+		String traceFilter = Platform.getDebugOption(PLUGIN_ID + TRACEFILTER_LOCATION);
+		if (traceFilter != null) {
+			StringTokenizer tokenizer = new StringTokenizer(traceFilter, ","); //$NON-NLS-1$
+			while (tokenizer.hasMoreTokens()) {
+				String cat = tokenizer.nextToken().trim();
+				if (category.equals(cat)) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	public static void log(int level, String message) {
+		_log(level, message, null);
+	}
+
+	public static void log(int level, String message, Throwable exception) {
+		_log(level, message, exception);
+	}
+
+	public static void logException(String message, Throwable exception) {
+		_log(ERROR, message, exception);
+	}
+
+	public static void logException(Throwable exception) {
+		_log(ERROR, exception.getMessage(), exception);
+	}
+
+	public static void trace(String category, String message) {
+		_trace(category, message, null);
+	}
+
+	public static void traceException(String category, String message, Throwable exception) {
+		_trace(category, message, exception);
+	}
+
+	public static void traceException(String category, Throwable exception) {
+		_trace(category, exception.getMessage(), exception);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/NullInputStream.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/NullInputStream.java
new file mode 100644
index 0000000..6b44f2f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/NullInputStream.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+
+public class NullInputStream extends InputStream {
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#mark(int)
+	 */
+	public synchronized void mark(int readlimit) {
+		// nothing to do
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#markSupported()
+	 */
+	public boolean markSupported() {
+		// we can mark nothing.
+		// and, we are using this Null class specifically for
+		// a "fake" resettable stream.
+		return true;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#read()
+	 */
+	public int read() throws IOException {
+
+		return -1;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#reset()
+	 */
+	public synchronized void reset() throws IOException {
+		// nothing to do
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#skip(long)
+	 */
+	public long skip(long n) throws IOException {
+		return 0;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/ResourceBundleHelper.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/ResourceBundleHelper.java
new file mode 100644
index 0000000..14aaa1f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/ResourceBundleHelper.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding.util;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import org.eclipse.core.runtime.Platform;
+
+//TODO: rework this with new platform/runtime APIs (if still needed).
+
+public class ResourceBundleHelper {
+
+	public static ResourceBundle getResourceBundle(String resourceURI) throws MalformedURLException, IOException {
+		return getResourceBundle(resourceURI, Locale.getDefault());
+	}
+
+	public static ResourceBundle getResourceBundle(String resourceURI, Locale targetLocale) throws MalformedURLException, IOException {
+		// try to load bundle from the location specified in the resourceURI
+		// we make the assumption that the resourceURI points to the local
+		// file system
+
+		int index = resourceURI.lastIndexOf("/"); //$NON-NLS-1$
+		if (index == -1) {
+			throw new IllegalArgumentException("Invalid resourceURI"); //$NON-NLS-1$
+		}
+
+		// Below we set 'resourceDirectory' so that it ends with a '/'.
+		// Here's an excerpt from the ClassLoader Javadoc ...
+		// Any URL that ends with a '/' is assumed to refer to a directory.
+		// Otherwise, the URL is assumed
+		// to refer to a JAR file which will be opened as needed.
+		//
+		String resourceDirectory = resourceURI.substring(0, index + 1);
+		String resourceBundleName = resourceURI.substring(index + 1);
+
+		// create a class loader with a class path that points to the resource
+		// bundle's location
+		//         
+		URL[] classpath = new URL[1];
+		classpath[0] = Platform.resolve(new URL(resourceDirectory));
+		ClassLoader resourceLoader = new URLClassLoader(classpath, null);
+
+		return ResourceBundle.getBundle(resourceBundleName, targetLocale, resourceLoader);
+	}
+}
+
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/UnicodeBOMEncodingDetector.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/UnicodeBOMEncodingDetector.java
new file mode 100644
index 0000000..e3c9d99
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/encoding/util/UnicodeBOMEncodingDetector.java
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.encoding.util;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.charset.Charset;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.IResourceCharsetDetector;
+
+
+/**
+ * This is a "common function" class to decide if an input stream, is a
+ * unicode stream.
+ */
+public class UnicodeBOMEncodingDetector implements IResourceCharsetDetector {
+
+	//private static final String UTF_16_CHARSET_NAME = "UTF-16";
+	// //$NON-NLS-1$
+
+	public static class NotEnoughInputForBOMException extends IOException {
+
+		/**
+		 * Default <code>serialVersionUID</code>
+		 */
+		private static final long serialVersionUID = 1L;
+
+		public NotEnoughInputForBOMException() {
+			super();
+		}
+
+		public NotEnoughInputForBOMException(String s) {
+			super(s);
+		}
+
+	}
+
+	private final static byte BB = (byte) 0xBB;
+	private final static byte BF = (byte) 0xBF;
+	private final static byte EF = (byte) 0xEF;
+	private final static byte FE = (byte) -2;
+
+	private final static byte FF = (byte) -1;
+	private static final String UTF_16BE_CHARSET_NAME = "UTF-16BE"; //$NON-NLS-1$
+	private static final String UTF_16LE_CHARSET_NAME = "UTF-16LE"; //$NON-NLS-1$
+
+	private static final String UTF_8_CHARSET_NAME = "UTF-8"; //$NON-NLS-1$
+
+	private InputStream fInputStream = null;
+	private boolean fNoBOMPossible;
+
+	private EncodingMemento checkForBOM(InputStream inputStream) {
+		EncodingMemento result = null;
+
+		try {
+			byte b1 = getNextByte(inputStream);
+			byte b2 = getNextByte(inputStream);
+			if (b1 == FE && b2 == FF) {
+				result = createEncodingMemento(UTF_16BE_CHARSET_NAME);
+				result.setUnicodeStream(true);
+			} else {
+				if (b1 == FF && b2 == FE) {
+					result = createEncodingMemento(UTF_16LE_CHARSET_NAME);
+					result.setUnicodeStream(true);
+				} else {
+					byte b3 = getNextByte((inputStream));
+					if (b1 == EF && b2 == BB && b3 == BF) {
+						result = createEncodingMemento(UTF_8_CHARSET_NAME);
+						result.setUTF83ByteBOMUsed(true);
+					}
+				}
+			}
+		} catch (NotEnoughInputForBOMException e) {
+			// This is sort of unexpected for normal cases, but can occur for
+			// empty
+			// streams. And, this can occur "normally" for non-BOM streams
+			// that
+			// have only two
+			// bytes, and for which those two bytes match the first two bytes
+			// of UTF-8
+			// BOM In any case, we'll simply return null;
+			result = null;
+		} catch (IOException e) {
+			// other errors should be impossible
+			throw new Error(e);
+		}
+
+		return result;
+	}
+
+	private EncodingMemento createEncodingMemento(String javaEncodingName) {
+		EncodingMemento encodingMemento = new EncodingMemento();
+		encodingMemento.setJavaCharsetName(javaEncodingName);
+		String ianaName = Charset.forName(javaEncodingName).name();
+		encodingMemento.setDetectedCharsetName(ianaName);
+		if (javaEncodingName.equals(UTF_8_CHARSET_NAME)) {
+			encodingMemento.setUTF83ByteBOMUsed(true);
+		}
+		return encodingMemento;
+	}
+
+	public String getEncoding() throws IOException {
+
+		return getEncodingMemento().getDetectedCharsetName();
+	}
+
+	/**
+	 * Returns IANA encoding name if BOM detected in stream. If a BOM is
+	 * detected, the stream is left positioned after readying the BOM. If a
+	 * BOM is not detected, the steam is reset.
+	 * 
+	 * 0xFEFF UTF-16, big-endian 0xFFFE UTF-16, little-endian 0xEFBBBF UTF-8
+	 * (BOM is optional)
+	 * 
+	 * @param inputStream -
+	 *            must be a resetable (mark supported) stream so it can be
+	 *            reset, if not BOM encoded stream
+	 * @return String - IANA encodingname (may not work well on 1.3, but 1.4
+	 *         seems to have good support for IANA names)
+	 */
+	public EncodingMemento getEncodingMemento() {
+
+		EncodingMemento result = null;
+		if (!fNoBOMPossible) {
+
+			if (fInputStream == null)
+				throw new IllegalStateException("input must be set before use"); //$NON-NLS-1$
+
+			if (!fInputStream.markSupported()) {
+				throw new IllegalArgumentException("inputStream must be resetable"); //$NON-NLS-1$
+			}
+
+			result = checkForBOM(fInputStream);
+		}
+
+		return result;
+
+	}
+
+	private byte getNextByte(InputStream inputStream) throws IOException {
+
+		int byteCharAsInt = -1;
+		// be sure we won't block
+		if (inputStream.available() > 0) {
+			byteCharAsInt = inputStream.read();
+			byteCharAsInt = byteCharAsInt & 0XFF;
+		}
+		// to avoid confustion over meaning of returned byte,
+		// throw exception if EOF reached.
+		if (byteCharAsInt == -1)
+			throw new NotEnoughInputForBOMException("typically not an error"); //$NON-NLS-1$
+		return (byte) byteCharAsInt;
+	}
+
+	/**
+	 *  
+	 */
+
+	public String getSpecDefaultEncoding() {
+		// There is no default for this case
+		return null;
+	}
+
+	/**
+	 *  
+	 */
+	private void resetAll() {
+		fNoBOMPossible = false;
+		fInputStream = null;
+
+	}
+
+	/**
+	 *  
+	 */
+
+	public void set(InputStream inputStream) {
+		resetAll();
+		fInputStream = inputStream;
+	}
+
+	public void set(IStorage iStorage) throws CoreException {
+		set(new BufferedInputStream(iStorage.getContents(), CodedIO.MAX_BUF_SIZE));
+
+	}
+
+	public void set(Reader reader) {
+		if (reader instanceof ByteReader) {
+			ByteReader byteReader = (ByteReader) reader;
+			fInputStream = byteReader.fInputStream;
+		} else {
+			fNoBOMPossible = true;
+		}
+
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/exceptions/CharConversionErrorWithDetail.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/exceptions/CharConversionErrorWithDetail.java
new file mode 100644
index 0000000..1f19444
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/exceptions/CharConversionErrorWithDetail.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.exceptions;
+
+import java.nio.charset.CharacterCodingException;
+
+
+public class CharConversionErrorWithDetail extends CharacterCodingException {
+	/**
+	 * Comment for <code>serialVersionUID</code>
+	 */
+	private static final long serialVersionUID = 1L;
+	private String fCharsetName;
+
+	public CharConversionErrorWithDetail() {
+		super();
+	}
+
+	/**
+	 * @param s
+	 */
+	public CharConversionErrorWithDetail(String charsetName) {
+		super();
+		fCharsetName = charsetName;
+	}
+
+	/**
+	 * @return Returns the fCharsetName.
+	 */
+	public String getCharsetName() {
+		return fCharsetName;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/exceptions/MalformedInputExceptionWithDetail.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/exceptions/MalformedInputExceptionWithDetail.java
new file mode 100644
index 0000000..ff31bbd
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/exceptions/MalformedInputExceptionWithDetail.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.exceptions;
+
+import java.nio.charset.CharacterCodingException;
+
+
+/**
+ * Intended to be a more precise form of the MalformedInputException, where
+ * character position and attempted encoding can be attempted.
+ */
+public class MalformedInputExceptionWithDetail extends CharacterCodingException {
+
+	/**
+	 * Default <code>serialVersionUID</code>
+	 */
+	private static final long serialVersionUID = 1L;
+	private int fCharPosition;
+	private String fDetectedCharsetName;
+	private boolean fExceededMax = false;
+	private String fJavaCharsetName;
+	private int fMaxBuffer;
+
+	/**
+	 * Disallow default constructor. If attemptedEncoding and charPostion can
+	 * not be provided, use one of java's MalformedException.
+	 */
+	protected MalformedInputExceptionWithDetail() {
+		// Nothing to do
+	}
+
+	public MalformedInputExceptionWithDetail(String encodingName, int charPostion) {
+		this.fJavaCharsetName = encodingName;
+		this.fDetectedCharsetName = encodingName;
+		this.fCharPosition = charPostion;
+	}
+
+	public MalformedInputExceptionWithDetail(String attemptedJavaEncoding, String attemptedIANAEncoding, int charPostion) {
+		this.fJavaCharsetName = attemptedJavaEncoding;
+		this.fDetectedCharsetName = attemptedIANAEncoding;
+		this.fCharPosition = charPostion;
+	}
+
+	/**
+	 * If charPosition = -1 this could be because the character position
+	 * exceeded the maximum buffer size, maxBuffer, then exceededMax = true.
+	 */
+	public MalformedInputExceptionWithDetail(String attemptedJavaEncoding, String attemptedIANAEncoding, int charPostion, boolean exceededMax, int maxBuffer) {
+		this.fJavaCharsetName = attemptedJavaEncoding;
+		this.fDetectedCharsetName = attemptedIANAEncoding;
+		this.fCharPosition = charPostion;
+		this.fExceededMax = exceededMax;
+		this.fMaxBuffer = maxBuffer;
+	}
+
+	/**
+	 */
+	public java.lang.String getAttemptedIANAEncoding() {
+		return fDetectedCharsetName;
+	}
+
+	/**
+	 */
+	public java.lang.String getAttemptedJavaEncoding() {
+		return fJavaCharsetName;
+	}
+
+	/**
+	 * @return int
+	 */
+	public int getCharPosition() {
+		return fCharPosition;
+	}
+
+	/**
+	 * Returns the maxBuffer.
+	 * 
+	 * @return int
+	 */
+	public int getMaxBuffer() {
+		return fMaxBuffer;
+	}
+
+	/**
+	 * Returns the exceededMax.
+	 * 
+	 * @return boolean
+	 */
+	public boolean isExceededMax() {
+		return fExceededMax;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/exceptions/MalformedOutputExceptionWithDetail.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/exceptions/MalformedOutputExceptionWithDetail.java
new file mode 100644
index 0000000..6eec680
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/exceptions/MalformedOutputExceptionWithDetail.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.exceptions;
+
+
+public class MalformedOutputExceptionWithDetail extends MalformedInputExceptionWithDetail {
+
+	/**
+	 * Default <code>serialVersionUID</code>
+	 */
+	private static final long serialVersionUID = 1L;
+
+
+	/**
+	 * Constructor for MalformedOutputExceptionWithDetail. If attemptedEncoding and charPostion can
+	 * not be provided, use sun.io.MalformedException.
+	 * 
+	 * @param attemptedJavaEncoding
+	 * @param attemptedIANAEncoding
+	 * @param charPostion
+	 */
+	public MalformedOutputExceptionWithDetail(String attemptedJavaEncoding, String attemptedIANAEncoding, int charPostion) {
+		super(attemptedJavaEncoding, attemptedIANAEncoding, charPostion);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/exceptions/UnsupportedCharsetExceptionWithDetail.java b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/exceptions/UnsupportedCharsetExceptionWithDetail.java
new file mode 100644
index 0000000..123af87
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-encoding/org/eclipse/wst/sse/core/internal/exceptions/UnsupportedCharsetExceptionWithDetail.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.exceptions;
+
+import java.nio.charset.UnsupportedCharsetException;
+
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+
+
+/**
+ * This is intended for same purpose as it super class, but simply provides
+ * more information about than the name in error. This is especially useful
+ * for "UIs" which can present users with the error, and the
+ * "appropriateDefault" that can be used for a particular input.
+ */
+public class UnsupportedCharsetExceptionWithDetail extends UnsupportedCharsetException {
+
+	/**
+	 * Default <code>serialVersionUID</code>
+	 */
+	private static final long serialVersionUID = 1L;
+	private EncodingMemento fEncodingMementio;
+
+	public UnsupportedCharsetExceptionWithDetail(EncodingMemento encodingMemento) {
+		this(encodingMemento.getDetectedCharsetName());
+		fEncodingMementio = encodingMemento;
+	}
+
+	protected UnsupportedCharsetExceptionWithDetail(String charsetName) {
+		super(charsetName);
+	}
+
+	public EncodingMemento getEncodingMemento() {
+		return fEncodingMementio;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/provisional/tasks/IFileTaskScanner.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/provisional/tasks/IFileTaskScanner.java
new file mode 100644
index 0000000..d1655b2
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/provisional/tasks/IFileTaskScanner.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.tasks;
+
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.sse.core.internal.SSECorePlugin;
+
+/**
+ * Scanners for the main Task Scanner. Scanners may be contributed using the
+ * org.eclipse.wst.sse.core.taskscanner extension point. For resources and
+ * resource deltas with matching content types, the main scanner will first
+ * call the startup() method, scan(), and then shutdown() in sequence. Scanner
+ * instances will be reused across projects but are not shared per content
+ * type. Scanners should not hold on to references to models or resources
+ * after shutdown() and should take care not to leak memory or resources.
+ */
+public interface IFileTaskScanner {
+	/**
+	 * Default marker type ID of task markers that are created.
+	 */
+	String TASK_MARKER_ID = SSECorePlugin.ID + ".task"; //$NON-NLS-1$;
+
+	/**
+	 * @return the task marker type that should be removed each time tasks are
+	 *         rescanned and used by default when creating task markers.
+	 *         Children of this marker type will be removed automatically.
+	 */
+	String getMarkerType();
+
+	/**
+	 * Requests that the list of automatically discovered tasks for the given
+	 * file be updated. Once completed, the list of tasks should correspond
+	 * exactly to the file's contents.
+	 * 
+	 * @param file -
+	 *            the file to be scanned
+	 * @param taskTags -
+	 *            the list of task tags for which to scan
+	 * @param monitor -
+	 *            a progress monitor
+	 * @return an array of maps containing the attributes of task markers to
+	 *         be created
+	 *         <p>
+	 *         The reserved attribute name
+	 *         <b>org.eclipse.core.resources.taskmarker</b> may be used to
+	 *         specify a type to use when creating the task marker.
+	 *         </p>
+	 */
+	Map[] scan(IFile file, TaskTag[] taskTags, IProgressMonitor monitor);
+
+	/**
+	 * Notifies the scanner that scanning is done for now. Resources held from
+	 * startup should now be released.
+	 * 
+	 * @param project -
+	 *            the project that was just scanned
+	 */
+	void shutdown(IProject project);
+
+	/**
+	 * Notifies the scanner that a sequence of scans is about to be requested.
+	 * Ideally the time to load preferences and perform any expensive
+	 * configuration for the given project.
+	 * 
+	 * @param project -
+	 *            the project that is about to be scanned
+	 * 
+	 */
+	void startup(IProject project);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/provisional/tasks/TaskTag.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/provisional/tasks/TaskTag.java
new file mode 100644
index 0000000..cab7258
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/provisional/tasks/TaskTag.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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.wst.sse.core.internal.provisional.tasks;
+
+import org.eclipse.core.resources.IMarker;
+
+/**
+ * Simple representation of the values that make up a Task Tag
+ */
+public final class TaskTag {
+
+	public static final int PRIORITY_HIGH = IMarker.PRIORITY_HIGH;
+	public static final int PRIORITY_LOW = IMarker.PRIORITY_LOW;
+	public static final int PRIORITY_NORMAL = IMarker.PRIORITY_NORMAL;
+
+	/**
+	 * this task tag's priority
+	 */
+	private int fPriority = PRIORITY_NORMAL;
+	
+	/**
+	 * this task tag's "tagging" text
+	 */
+	private String fTag = null;
+
+	public TaskTag(String tag, int priority) {
+		super();
+		fTag = tag;
+		fPriority = priority;
+	}
+
+	public int getPriority() {
+		return fPriority;
+	}
+
+	public String getTag() {
+		return fTag;
+	}
+
+	public String toString() {
+		return getTag() + ":" + getPriority(); //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/FileTaskScannerRegistryReader.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/FileTaskScannerRegistryReader.java
new file mode 100644
index 0000000..34b9c07
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/FileTaskScannerRegistryReader.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (Intalio) - bug 300434 - Make inner classes static where possibl *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.tasks;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.content.IContentTypeManager;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.SSECorePlugin;
+import org.eclipse.wst.sse.core.internal.provisional.tasks.IFileTaskScanner;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+
+public class FileTaskScannerRegistryReader {
+	private static class ScannerInfo {
+		String fId;
+		IFileTaskScanner fScanner;
+
+		ScannerInfo(String id, IFileTaskScanner scanner) {
+			super();
+			fId = id;
+			fScanner = scanner;
+		}
+
+		public boolean equals(Object obj) {
+			return obj instanceof ScannerInfo && fId.equals(((ScannerInfo) obj).fId);
+		}
+
+		public IFileTaskScanner getScanner() {
+			return fScanner;
+		}
+	}
+
+	private static FileTaskScannerRegistryReader _instance = null;
+
+	public static FileTaskScannerRegistryReader getInstance() {
+		if (_instance == null) {
+			_instance = new FileTaskScannerRegistryReader();
+		}
+		return _instance;
+	}
+
+	private String ATT_CLASS = "class"; //$NON-NLS-1$
+
+	private String ATT_CONTENT_TYPES = "contentTypeIds"; //$NON-NLS-1$
+
+	private String ATT_ID = "id"; //$NON-NLS-1$
+
+	private IConfigurationElement[] fScannerElements;
+
+	// a mapping from content types to ScannerInfo instances
+	private Map fScannerInfos = null;
+
+	private String NAME_SCANNER = "scanner"; //$NON-NLS-1$
+
+	private String SCANNER_EXTENSION_POINT_ID = SSECorePlugin.ID + ".taskscanner"; //$NON-NLS-1$
+
+	private FileTaskScannerRegistryReader() {
+		super();
+	}
+
+	IFileTaskScanner[] getFileTaskScanners(IContentType[] contentTypes) {
+		if (fScannerElements == null) {
+			readRegistry();
+		}
+
+		List scannerInfos = new ArrayList(1);
+
+		for (int i = 0; i < contentTypes.length; i++) {
+			ScannerInfo[] scannerInfosForContentType = (ScannerInfo[]) fScannerInfos.get(contentTypes[i].getId());
+			if (scannerInfosForContentType == null) {
+				scannerInfosForContentType = loadScanners(contentTypes[i]);
+			}
+			// only add non-duplicate scanners
+			for (int j = 0; j < scannerInfosForContentType.length; j++) {
+				if (!scannerInfos.contains(scannerInfosForContentType[j])) {
+					scannerInfos.add(scannerInfosForContentType[j]);
+				}
+			}
+		}
+		IFileTaskScanner[] scanners = new IFileTaskScanner[scannerInfos.size()];
+		for (int i = 0; i < scanners.length; i++) {
+			scanners[i] = ((ScannerInfo) scannerInfos.get(i)).getScanner();
+		}
+		return scanners;
+	}
+
+	public String[] getSupportedContentTypeIds() {
+		if (fScannerElements == null) {
+			readRegistry();
+		}
+
+		// find the relevant extensions
+		List types = new ArrayList(0);
+		IConfigurationElement[] scannerElements = fScannerElements;
+		for (int j = 0; j < scannerElements.length; j++) {
+			if (!scannerElements[j].getName().equals(NAME_SCANNER))
+				continue;
+			String[] contentTypeIds = StringUtils.unpack(scannerElements[j].getAttribute(ATT_CONTENT_TYPES));
+			for (int i = 0; i < contentTypeIds.length; i++) {
+				if (!types.contains(contentTypeIds[i])) {
+					types.add(contentTypeIds[i]);
+				}
+			}
+		}
+
+		return (String[]) types.toArray(new String[types.size()]);
+	}
+
+	private ScannerInfo[] loadScanners(IContentType contentType) {
+		List elements = new ArrayList(0);
+		ScannerInfo[] scannerInfos = null;
+		IConfigurationElement[] delegateElements = fScannerElements;
+		if (contentType != null) {
+			IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
+			for (int j = 0; j < delegateElements.length; j++) {
+				if (!delegateElements[j].getName().equals(NAME_SCANNER))
+					continue;
+				String[] supportedContentTypeIds = StringUtils.unpack(delegateElements[j].getAttribute(ATT_CONTENT_TYPES));
+				IContentType[] supportedContentTypes = new IContentType[supportedContentTypeIds.length];
+				for (int k = 0; k < supportedContentTypeIds.length; k++) {
+					supportedContentTypes[k] = contentTypeManager.getContentType(supportedContentTypeIds[k].trim());
+				}
+				for (int k = 0; k < supportedContentTypeIds.length; k++) {
+					// allow subtypes to be returned as well
+					if (supportedContentTypes[k] != null && contentType.isKindOf(supportedContentTypes[k])) {
+						elements.add(delegateElements[j]);
+					}
+				}
+			}
+			// instantiate and save the scanners
+			List scannerInfoList = new ArrayList(elements.size());
+			for (int i = 0; i < elements.size(); i++) {
+				try {
+					IFileTaskScanner scanner = (IFileTaskScanner) ((IConfigurationElement) elements.get(i)).createExecutableExtension(ATT_CLASS);
+					if (scanner != null) {
+						scannerInfoList.add(new ScannerInfo(((IConfigurationElement) elements.get(i)).getAttribute(ATT_ID), scanner));
+					}
+				}
+				catch (CoreException e) {
+					Logger.logException("Non-fatal exception creating task scanner for " + contentType.getId(), e); //$NON-NLS-1$
+				}
+			}
+			scannerInfos = (ScannerInfo[]) scannerInfoList.toArray(new ScannerInfo[scannerInfoList.size()]);
+			fScannerInfos.put(contentType.getId(), scannerInfos);
+			if (Logger.DEBUG_TASKSREGISTRY) {
+				System.out.println("Created " + scannerInfos.length + " task scanner for " + contentType.getId()); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}
+		return scannerInfos;
+	}
+
+	private void readRegistry() {
+		fScannerInfos = new HashMap();
+		// Just remember the elements, so plugins don't have to be activated,
+		// unless extension attributes match those of interest
+		IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(SCANNER_EXTENSION_POINT_ID);
+		if (point != null) {
+			fScannerElements = point.getConfigurationElements();
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/StructuredFileTaskScanner.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/StructuredFileTaskScanner.java
new file mode 100644
index 0000000..42271b4
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/StructuredFileTaskScanner.java
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.tasks;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.CharacterCodingException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.document.DocumentReader;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionHandler;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionParser;
+import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry;
+import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument;
+import org.eclipse.wst.sse.core.internal.provisional.tasks.IFileTaskScanner;
+import org.eclipse.wst.sse.core.internal.provisional.tasks.TaskTag;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+
+/**
+ * A delegate to create IMarker.TASKs for "todos" and similar comments.
+ */
+public abstract class StructuredFileTaskScanner implements IFileTaskScanner, IExecutableExtension {
+	// the list of attributes for the new tasks for the current file
+	protected List fNewMarkerAttributeMaps = null;
+
+	List oldMarkers = null;
+	private long time0;
+	private String runtimeMarkerType;
+
+	public StructuredFileTaskScanner() {
+		super();
+		fNewMarkerAttributeMaps = new ArrayList();
+		if (Logger.DEBUG_TASKS) {
+			System.out.println(getClass().getName() + " instance created"); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Returns the attributes with which a newly created marker will be
+	 * initialized. Modified from the method in MarkerRulerAction
+	 * 
+	 * @return the initial marker attributes
+	 */
+	protected Map createInitialMarkerAttributes(String text, int documentLine, int startOffset, int length, int priority) {
+		Map attributes = new HashMap(6);
+		// marker line numbers are 1-based
+		attributes.put(IMarker.LINE_NUMBER, new Integer(documentLine + 1));
+		attributes.put(IMarker.TASK, getMarkerType());
+		attributes.put(IMarker.CHAR_START, new Integer(startOffset));
+		attributes.put(IMarker.CHAR_END, new Integer(startOffset + length));
+		attributes.put(IMarker.MESSAGE, text);
+		attributes.put(IMarker.USER_EDITABLE, Boolean.FALSE);
+
+		switch (priority) {
+			case IMarker.PRIORITY_HIGH : {
+				attributes.put(IMarker.PRIORITY, new Integer(IMarker.PRIORITY_HIGH));
+			}
+				break;
+			case IMarker.PRIORITY_LOW : {
+				attributes.put(IMarker.PRIORITY, new Integer(IMarker.PRIORITY_LOW));
+			}
+				break;
+			default : {
+				attributes.put(IMarker.PRIORITY, new Integer(IMarker.PRIORITY_NORMAL));
+			}
+		}
+
+		return attributes;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.internal.provisional.tasks.IFileTaskScanner#getMarkerType()
+	 */
+	public String getMarkerType() {
+		if (runtimeMarkerType != null)
+			return runtimeMarkerType;
+
+		return org.eclipse.core.resources.IMarker.TASK;
+	}
+
+	private String detectCharset(IFile file) {
+		if (file.getType() == IResource.FILE && file.isAccessible()) {
+			try {
+				return file.getCharset(true);
+			}
+			catch (CoreException e) {
+				Logger.logException(e);
+			}
+		}
+		return ResourcesPlugin.getEncoding();
+	}
+
+	/**
+	 * @param document
+	 * @param documentRegion
+	 * @param comment
+	 */
+	protected void findTasks(IDocument document, TaskTag[] taskTags, IStructuredDocumentRegion documentRegion, ITextRegion comment) {
+		if (isCommentRegion(documentRegion, comment)) {
+			int startOffset = documentRegion.getStartOffset(comment);
+			int endOffset = documentRegion.getTextEndOffset(comment);
+			try {
+				int startLine = document.getLineOfOffset(startOffset);
+				int endLine = document.getLineOfOffset(endOffset);
+				for (int lineNumber = startLine; lineNumber <= endLine; lineNumber++) {
+					IRegion line = document.getLineInformation(lineNumber);
+					int begin = Math.max(startOffset, line.getOffset());
+					int end = Math.min(endOffset, line.getOffset() + line.getLength());
+					int length = end - begin;
+
+					/* XXX: This generates a lot of garbage objects */
+
+					String commentedText = getCommentedText(document, begin, length);
+					String comparisonText = commentedText.toLowerCase(Locale.ENGLISH);
+
+					for (int i = 0; i < taskTags.length; i++) {
+						int tagIndex = comparisonText.indexOf(taskTags[i].getTag().toLowerCase(Locale.ENGLISH));
+						if (tagIndex >= 0) {
+							String markerDescription = commentedText.substring(tagIndex);
+							int markerOffset = begin + tagIndex;
+							int markerLength = end - markerOffset;
+							fNewMarkerAttributeMaps.add(createInitialMarkerAttributes(markerDescription, lineNumber, markerOffset, markerLength, taskTags[i].getPriority()));
+						}
+					}
+				}
+			}
+			catch (BadLocationException e) {
+				Logger.logException(e);
+			}
+		}
+	}
+
+	private void findTasks(IFile file, final TaskTag[] taskTags, final IProgressMonitor monitor) {
+		try {
+			IModelHandler handler = ModelHandlerRegistry.getInstance().getHandlerFor(file);
+
+			// records if the optimized streamish parse was possible
+			boolean didStreamParse = false;
+			final IEncodedDocument defaultDocument = handler.getDocumentLoader().createNewStructuredDocument();
+			if (defaultDocument instanceof IStructuredDocument) {
+				RegionParser parser = ((IStructuredDocument) defaultDocument).getParser();
+				if (parser instanceof StructuredDocumentRegionParser) {
+					didStreamParse = true;
+					String charset = detectCharset(file);
+					StructuredDocumentRegionParser documentParser = (StructuredDocumentRegionParser) parser;
+					final IDocument textDocument = new Document();
+					setDocumentContent(textDocument, file.getContents(true), charset);
+					monitor.beginTask("", textDocument.getLength());
+					documentParser.reset(new DocumentReader(textDocument));
+					documentParser.addStructuredDocumentRegionHandler(new StructuredDocumentRegionHandler() {
+						public void nodeParsed(IStructuredDocumentRegion documentRegion) {
+							ITextRegionList regions = documentRegion.getRegions();
+							for (int j = 0; j < regions.size(); j++) {
+								ITextRegion comment = regions.get(j);
+								findTasks(textDocument, taskTags, documentRegion, comment);
+							}
+							// disconnect the document regions
+							if (documentRegion.getPrevious() != null) {
+								documentRegion.getPrevious().setPrevious(null);
+								documentRegion.getPrevious().setNext(null);
+							}
+							if (monitor.isCanceled()) {
+								textDocument.set(""); //$NON-NLS-1$
+							}
+							monitor.worked(documentRegion.getLength());
+						}
+
+						public void resetNodes() {
+						}
+					});
+					documentParser.getDocumentRegions();
+				}
+			}
+			if (!didStreamParse) {
+				// Use a StructuredDocument
+				IEncodedDocument document = handler.getDocumentLoader().createNewStructuredDocument(file);
+				monitor.beginTask("", document.getLength());
+				if (document instanceof IStructuredDocument) {
+					IStructuredDocumentRegion documentRegion = ((IStructuredDocument) document).getFirstStructuredDocumentRegion();
+					while (documentRegion != null) {
+						ITextRegionList regions = documentRegion.getRegions();
+						for (int j = 0; j < regions.size(); j++) {
+							ITextRegion comment = regions.get(j);
+							findTasks(document, taskTags, documentRegion, comment);
+						}
+						monitor.worked(documentRegion.getLength());
+						documentRegion = documentRegion.getNext();
+					}
+				}
+			}
+		}
+		catch (CoreException e) {
+			Logger.logException("Exception with " + file.getFullPath().toString(), e); //$NON-NLS-1$
+		}
+		catch (CharacterCodingException e) {
+			Logger.log(Logger.INFO, "StructuredFileTaskScanner encountered CharacterCodingException reading " + file.getFullPath()); //$NON-NLS-1$
+		}
+		catch (Exception e) {
+			Logger.logException("Exception with " + file.getFullPath().toString(), e); //$NON-NLS-1$
+		}
+		monitor.done();
+	}
+
+	protected String getCommentedText(IDocument document, int begin, int length) throws BadLocationException {
+		return document.get(begin, length);
+	}
+
+	protected abstract boolean isCommentRegion(IStructuredDocumentRegion region, ITextRegion textRegion);
+
+	public synchronized Map[] scan(IFile file, TaskTag[] taskTags, IProgressMonitor monitor) {
+		fNewMarkerAttributeMaps.clear();
+		if (monitor.isCanceled() || !shouldScan(file)) {
+			return new Map[0];
+		}
+		if (Logger.DEBUG_TASKSPERF) {
+			time0 = System.currentTimeMillis();
+		}
+		if (taskTags.length > 0) {
+			findTasks(file, taskTags, monitor);
+		}
+		if (Logger.DEBUG_TASKSPERF) {
+			System.out.println("" + (System.currentTimeMillis() - time0) + "ms for " + file.getFullPath()); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		return (Map[]) fNewMarkerAttributeMaps.toArray(new Map[fNewMarkerAttributeMaps.size()]);
+	}
+
+	/**
+	 * Sets the document content from this stream and closes the stream
+	 */
+	protected void setDocumentContent(IDocument document, InputStream contentStream, String charset) {
+		Reader in = null;
+		try {
+			in = new BufferedReader(new InputStreamReader(contentStream, charset), 2048);
+			StringBuffer buffer = new StringBuffer(2048);
+			char[] readBuffer = new char[2048];
+			int n = in.read(readBuffer);
+			while (n > 0) {
+				buffer.append(readBuffer, 0, n);
+				n = in.read(readBuffer);
+			}
+			document.set(buffer.toString());
+		}
+		catch (IOException x) {
+		}
+		finally {
+			if (in != null) {
+				try {
+					in.close();
+				}
+				catch (IOException x) {
+				}
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement,
+	 *      java.lang.String, java.lang.Object)
+	 */
+	public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+		if (data != null && data instanceof String) {
+			runtimeMarkerType = data.toString();
+		}
+	}
+
+	boolean shouldScan(IResource r) {
+		// skip "dot" files
+		String s = r.getName();
+		return s.length() == 0 || s.charAt(0) != '.';
+	}
+
+	public void shutdown(IProject project) {
+		if (Logger.DEBUG_TASKS) {
+			System.out.println(this + " shutdown for " + project.getName()); //$NON-NLS-1$
+		}
+	}
+
+	public void startup(IProject project) {
+		if (Logger.DEBUG_TASKS) {
+			System.out.println(this + " startup for " + project.getName()); //$NON-NLS-1$
+		}
+		if (Logger.DEBUG_TASKSPERF) {
+			time0 = System.currentTimeMillis();
+		}
+		if (Logger.DEBUG_TASKSPERF) {
+			System.out.println("" + (System.currentTimeMillis() - time0) + "ms loading prefs for " + project.getName()); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskScanningJob.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskScanningJob.java
new file mode 100644
index 0000000..92fda63
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskScanningJob.java
@@ -0,0 +1,251 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     David Carver (Intalio) - bug 300443 - some constants aren't static final
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.tasks;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.SSECoreMessages;
+import org.eclipse.wst.sse.core.internal.SSECorePlugin;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.osgi.framework.Bundle;
+
+/**
+ * Queueing Job for processing deltas and projects.
+ */
+class TaskScanningJob extends Job {
+	static final int JOB_DELAY_DELTA = 1000;
+	private static final int JOB_DELAY_PROJECT = 5000;
+	static final String TASK_TAG_PROJECTS_ALREADY_SCANNED = "task-tag-projects-already-scanned"; //$NON-NLS-1$
+	private List fQueue = null;
+
+	/** symbolic name for OSGI framework */
+	private static final String OSGI_FRAMEWORK_ID = "org.eclipse.osgi"; //$NON-NLS-1$
+
+	TaskScanningJob() {
+		super(SSECoreMessages.TaskScanner_0);
+		fQueue = new ArrayList();
+		setPriority(Job.DECORATE);
+		setSystem(true);
+		setUser(false);
+
+		SSECorePlugin.getDefault().getPluginPreferences().setDefault(TASK_TAG_PROJECTS_ALREADY_SCANNED, ""); //$NON-NLS-1$
+	}
+
+	synchronized void addProjectDelta(IResourceDelta delta) {
+		IResource projectResource = delta.getResource();
+
+		if (projectResource.getType() == IResource.PROJECT) {
+			if (isEnabledOnProject((IProject) projectResource)) {
+				fQueue.add(delta);
+				if (Logger.DEBUG_TASKSJOB) {
+					String kind = null;
+					switch (delta.getKind()) {
+						case IResourceDelta.ADDED :
+							kind = " [IResourceDelta.ADDED]"; //$NON-NLS-1$
+							break;
+						case IResourceDelta.CHANGED :
+							kind = " [IResourceDelta.CHANGED]"; //$NON-NLS-1$
+							break;
+						case IResourceDelta.REMOVED :
+							kind = " [IResourceDelta.REMOVED]"; //$NON-NLS-1$
+							break;
+						case IResourceDelta.ADDED_PHANTOM :
+							kind = " [IResourceDelta.ADDED_PHANTOM]"; //$NON-NLS-1$
+							break;
+						case IResourceDelta.REMOVED_PHANTOM :
+							kind = " [IResourceDelta.REMOVED_PHANTOM]"; //$NON-NLS-1$
+							break;
+					}
+					System.out.println("Adding delta " + delta.getFullPath() + kind); //$NON-NLS-1$
+				}
+				schedule(JOB_DELAY_DELTA);
+			}
+		}
+	}
+
+	synchronized void addProject(IProject project) {
+		if (projectHasNotBeenFullyScanned(project)) {
+			fQueue.add(project);
+			if (Logger.DEBUG_TASKSJOB) {
+				System.out.println("Adding project " + project.getName()); //$NON-NLS-1$
+			}
+			schedule(JOB_DELAY_PROJECT);
+		}
+	}
+
+	/**
+	 * A check to see if the OSGI framework is shutting down.
+	 * 
+	 * @return true if the System Bundle is stopped (ie. the framework is
+	 *         shutting down)
+	 */
+	boolean frameworkIsShuttingDown() {
+		// in the Framework class there's a note:
+		// set the state of the System Bundle to STOPPING.
+		// this must be done first according to section 4.19.2 from the OSGi
+		// R3 spec.
+		boolean shuttingDown = !Platform.isRunning() || Platform.getBundle(OSGI_FRAMEWORK_ID).getState() == Bundle.STOPPING;
+		if (Logger.DEBUG_TASKSJOB && shuttingDown) {
+			System.out.println("TaskScanningJob: system is shutting down!"); //$NON-NLS-1$
+		}
+		return shuttingDown;
+	}
+	
+	private boolean isEnabledOnProject(IProject p) {
+		IPreferencesService preferencesService = Platform.getPreferencesService();
+		IScopeContext[] lookupOrder = new IScopeContext[]{new ProjectScope(p), new InstanceScope(), new DefaultScope()};
+		return preferencesService.getBoolean(TaskTagPreferenceKeys.TASK_TAG_NODE, TaskTagPreferenceKeys.TASK_TAG_ENABLE, false, lookupOrder);
+	}
+
+	private boolean projectHasNotBeenFullyScanned(IResource project) {
+		String[] projectsScanned = StringUtils.unpack(SSECorePlugin.getDefault().getPluginPreferences().getString(TASK_TAG_PROJECTS_ALREADY_SCANNED));
+
+		boolean shouldScan = true;
+		String name = project.getName();
+		for (int j = 0; shouldScan && j < projectsScanned.length; j++) {
+			if (projectsScanned[j].equals(name)) {
+				if (Logger.DEBUG_TASKSJOB)
+					System.out.println("Scanning Job skipping " + project.getName()); //$NON-NLS-1$
+				shouldScan = false;
+			}
+		}
+		return shouldScan;
+	}
+
+	synchronized List retrieveQueue() {
+		List queue = fQueue;
+		fQueue = new ArrayList();
+		return queue;
+	}
+
+	protected IStatus run(IProgressMonitor monitor) {
+		if (frameworkIsShuttingDown())
+			return Status.CANCEL_STATUS;
+
+		cleanupRememberedProjectList(TASK_TAG_PROJECTS_ALREADY_SCANNED);
+
+		IStatus status = null;
+		List currentQueue = retrieveQueue();
+		
+		try {
+			Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
+		}
+		catch (SecurityException e) {
+			// not a critical problem
+		}
+		
+		List errors = null;
+		int ticks = currentQueue.size();
+		String taskName = null;
+		if (Logger.DEBUG_TASKSJOB) {
+			taskName = SSECoreMessages.TaskScanningJob_0 + " (" + ticks + " work items)"; //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		else {
+			taskName = SSECoreMessages.TaskScanningJob_0;
+		}
+		monitor.beginTask(taskName, ticks);
+
+		IProgressMonitor scanMonitor = null;
+		while (!currentQueue.isEmpty()) {
+			Object o = currentQueue.remove(0);
+			if (frameworkIsShuttingDown() || monitor.isCanceled())
+				return Status.CANCEL_STATUS;
+			try {
+				scanMonitor = new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+				if (o instanceof IResourceDelta) {
+					WorkspaceTaskScanner.getInstance().scan((IResourceDelta) o, scanMonitor);
+				}
+				else if (o instanceof IProject) {
+					WorkspaceTaskScanner.getInstance().scan((IProject) o, scanMonitor);
+					if(!scanMonitor.isCanceled() ) {
+						String[] projectsPreviouslyScanned = StringUtils.unpack(SSECorePlugin.getDefault().getPluginPreferences().getString(TASK_TAG_PROJECTS_ALREADY_SCANNED));
+						String[] updatedProjects = new String[projectsPreviouslyScanned.length + 1];
+						updatedProjects[projectsPreviouslyScanned.length] = ((IResource) o).getName();
+						System.arraycopy(projectsPreviouslyScanned, 0, updatedProjects, 0, projectsPreviouslyScanned.length);
+						SSECorePlugin.getDefault().getPluginPreferences().setValue(TASK_TAG_PROJECTS_ALREADY_SCANNED, StringUtils.pack(updatedProjects));
+					}
+				}
+			}
+			catch (Exception e) {
+				if (errors == null) {
+					errors = new ArrayList();
+				}
+				errors.add(new Status(IStatus.ERROR, SSECorePlugin.ID, IStatus.ERROR, "", e)); //$NON-NLS-1$
+			}
+		}
+		monitor.done();
+
+		if (errors == null || errors.isEmpty()) {
+			status = Status.OK_STATUS;
+		}
+		else {
+			if (errors.size() == 1) {
+				status = (IStatus) errors.get(0);
+			}
+			else {
+				IStatus[] statii = (IStatus[]) errors.toArray(new IStatus[errors.size()]);
+				status = new MultiStatus(SSECorePlugin.ID, IStatus.ERROR, statii, SSECoreMessages.TaskScanningJob_1, null);
+			}
+		}
+
+		SSECorePlugin.getDefault().savePluginPreferences();
+		return status;
+	}
+
+	private void cleanupRememberedProjectList(String preferenceName) {
+		String[] rememberedProjectNames = StringUtils.unpack(SSECorePlugin.getDefault().getPluginPreferences().getString(preferenceName));
+		IResource[] workspaceProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+		String[] projectNames = new String[workspaceProjects.length];
+		for (int i = 0; i < projectNames.length; i++) {
+			projectNames[i] = workspaceProjects[i].getName();
+		}
+
+		List projectNamesToRemember = new ArrayList(rememberedProjectNames.length);
+		for (int i = 0; i < rememberedProjectNames.length; i++) {
+			boolean rememberedProjectExists = false;
+			for (int j = 0; !rememberedProjectExists && j < projectNames.length; j++) {
+				if (rememberedProjectNames[i].equals(projectNames[j])) {
+					rememberedProjectExists = true;
+				}
+			}
+			if (rememberedProjectExists) {
+				projectNamesToRemember.add(rememberedProjectNames[i]);
+			}
+			else if (Logger.DEBUG_TASKSJOB) {
+				System.out.println("Removing " + rememberedProjectNames[i] + " removed from " + preferenceName); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}
+
+		if (projectNamesToRemember.size() != rememberedProjectNames.length) {
+			SSECorePlugin.getDefault().getPluginPreferences().setValue(preferenceName, StringUtils.pack((String[]) projectNamesToRemember.toArray(new String[projectNamesToRemember.size()])));
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskScanningScheduler.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskScanningScheduler.java
new file mode 100644
index 0000000..6095a6d
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskScanningScheduler.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 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.wst.sse.core.internal.tasks;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.SSECorePlugin;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+
+public class TaskScanningScheduler {
+	class ListenerVisitor implements IResourceChangeListener, IResourceDeltaVisitor {
+		public void resourceChanged(IResourceChangeEvent event) {
+			IResourceDelta delta = event.getDelta();
+			if (delta.getResource() != null) {
+				int resourceType = delta.getResource().getType();
+				if (resourceType == IResource.PROJECT || resourceType == IResource.ROOT) {
+					try {
+						delta.accept(this);
+					}
+					catch (CoreException e) {
+						Logger.logException("Exception handling resource change", e); //$NON-NLS-1$
+					}
+				}
+			}
+		}
+
+		public boolean visit(IResourceDelta delta) throws CoreException {
+			if ((delta.getKind() & IResourceDelta.MARKERS) > 0 || (delta.getKind() & IResourceDelta.ENCODING) > 0 || (delta.getKind() & IResourceDelta.NO_CHANGE) > 0)
+				return false;
+
+			IResource resource = delta.getResource();
+			if (resource != null) {
+				if (resource.getType() == IResource.ROOT)
+					return true;
+				else if (resource.getType() == IResource.PROJECT) {
+					fJob.addProjectDelta(delta);
+					return false;
+				}
+			}
+			return false;
+		}
+
+	}
+
+	private static TaskScanningScheduler scheduler;
+
+	public static void refresh() {
+		SSECorePlugin.getDefault().getPluginPreferences().setValue(TaskScanningJob.TASK_TAG_PROJECTS_ALREADY_SCANNED, ""); //$NON-NLS-1$
+		scheduler.enqueue(ResourcesPlugin.getWorkspace().getRoot());
+	}
+
+	public static void refresh(IProject project) {
+		String[] projectNames = StringUtils.unpack(SSECorePlugin.getDefault().getPluginPreferences().getString(TaskScanningJob.TASK_TAG_PROJECTS_ALREADY_SCANNED)); //$NON-NLS-1$
+		List freshProjectList = new ArrayList();
+		for (int i = 0; i < projectNames.length; i++) {
+			if (!projectNames[i].equals(project.getName())) {
+				freshProjectList.add(projectNames[i]);
+			}
+		}
+		String freshProjects = StringUtils.pack((String[]) freshProjectList.toArray(new String[freshProjectList.size()]));
+		SSECorePlugin.getDefault().getPluginPreferences().setValue(TaskScanningJob.TASK_TAG_PROJECTS_ALREADY_SCANNED, freshProjects); //$NON-NLS-1$
+
+		scheduler.enqueue(project);
+	}
+
+
+	/**
+	 * Only for use by SSECorePlugin class
+	 */
+	public static void shutdown() {
+		if (scheduler != null) {
+			ResourcesPlugin.getWorkspace().removeResourceChangeListener(scheduler.visitor);
+			scheduler.fJob.cancel();
+			try {
+				scheduler.fJob.join();
+			}
+			catch (InterruptedException e) {
+				Logger.logException(e);
+			}
+		}
+	}
+
+	/**
+	 * Only for use by SSEUIPlugin class, UI by nature of its output being meant for the user
+	 */
+	public static void startup() {
+		scheduler = new TaskScanningScheduler();
+
+		/*
+		 * According to
+		 * http://www.eclipse.org/eclipse/development/performance/bloopers.html,
+		 * POST_CHANGE listeners add a trivial performance cost.
+		 * 
+		 * Always add listener since we might be enabled per-project even if disabled workspace-wide.
+		 */
+		ResourcesPlugin.getWorkspace().addResourceChangeListener(scheduler.visitor, IResourceChangeEvent.POST_CHANGE);
+
+		scheduler.enqueue(ResourcesPlugin.getWorkspace().getRoot());
+	}
+
+	TaskScanningJob fJob = null;
+
+	ListenerVisitor visitor = null;
+
+	private TaskScanningScheduler() {
+		super();
+		fJob = new TaskScanningJob();
+		visitor = new ListenerVisitor();
+	}
+
+	void enqueue(IProject project) {
+		fJob.addProject(project);
+	}
+
+	void enqueue(IWorkspaceRoot root) {
+		IProject[] allProjects = root.getProjects();
+		for (int i = 0; i < allProjects.length; i++) {
+			fJob.addProject(allProjects[i]);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskTagPreferenceKeys.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskTagPreferenceKeys.java
new file mode 100644
index 0000000..bb3e305
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/TaskTagPreferenceKeys.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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.wst.sse.core.internal.tasks;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.wst.sse.core.internal.SSECorePlugin;
+
+public final class TaskTagPreferenceKeys {
+	public static final String TASK_TAG_CONTENTTYPES_IGNORED = "ignored-contentTypes"; //$NON-NLS-1$
+	public static final String TASK_TAG_ENABLE = "enabled"; //$NON-NLS-1$
+	public static final String TASK_TAG_NODE = SSECorePlugin.ID + IPath.SEPARATOR + "task-tags"; //$NON-NLS-1$
+	public static final String TASK_TAG_PER_PROJECT = "use-project-settings"; //$NON-NLS-1$
+	public static final String TASK_TAG_PRIORITIES = "taskPriorities"; //$NON-NLS-1$
+	public static final String TASK_TAG_TAGS = "taskTags"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/WorkspaceTaskScanner.java b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/WorkspaceTaskScanner.java
new file mode 100644
index 0000000..3f3ffa6
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src-tasktags/org/eclipse/wst/sse/core/internal/tasks/WorkspaceTaskScanner.java
@@ -0,0 +1,467 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (Intalio) - bug 300443 - some constants aren't static final
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.tasks;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.content.IContentTypeManager;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.provisional.tasks.IFileTaskScanner;
+import org.eclipse.wst.sse.core.internal.provisional.tasks.TaskTag;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+
+/**
+ * Dispatcher for scanning based on deltas and requested projects
+ */
+class WorkspaceTaskScanner {
+	private static WorkspaceTaskScanner _instance = null;
+	static final String SYNTHETIC_TASK = "org.eclipse.wst.sse.task-synthetic";
+	static final String MODIFICATION_STAMP = "org.eclipse.wst.sse.modification-stamp";
+	private boolean proceed = false;
+
+	static synchronized WorkspaceTaskScanner getInstance() {
+		if (_instance == null) {
+			_instance = new WorkspaceTaskScanner();
+		}
+		return _instance;
+	}
+
+	static final String DEFAULT_MARKER_TYPE = IFileTaskScanner.TASK_MARKER_ID;
+	private List fActiveScanners = null;
+	private IContentType[] fCurrentIgnoreContentTypes = null;
+	private TaskTag[] fCurrentTaskTags = null;
+
+	private FileTaskScannerRegistryReader registry = null;
+
+	private long time0;
+
+	/**
+	 * 
+	 */
+	private WorkspaceTaskScanner() {
+		super();
+		registry = FileTaskScannerRegistryReader.getInstance();
+		fActiveScanners = new ArrayList();
+		fCurrentTaskTags = new TaskTag[0];
+		fCurrentIgnoreContentTypes = new IContentType[0];
+	}
+
+	private IContentType[] detectContentTypes(IResource resource) {
+		IContentType[] types = null;
+		if (resource.getType() == IResource.FILE && resource.isAccessible()) {
+			types = Platform.getContentTypeManager().findContentTypesFor(resource.getName());
+			if (types.length == 0) {
+				IContentDescription d = null;
+				try {
+					// optimized description lookup, might not succeed
+					d = ((IFile) resource).getContentDescription();
+					if (d != null) {
+						types = new IContentType[]{d.getContentType()};
+					}
+				}
+				catch (CoreException e) {
+					/*
+					 * should not be possible given the accessible and file
+					 * type check above
+					 */
+				}
+			}
+			if (types == null) {
+				types = Platform.getContentTypeManager().findContentTypesFor(resource.getName());
+			}
+			if (Logger.DEBUG_TASKSCONTENTTYPE) {
+				if (types.length > 0) {
+					if (types.length > 1) {
+						System.out.println(resource.getFullPath() + ": " + "multiple based on name (probably hierarchical)"); //$NON-NLS-1$ //$NON-NLS-2$
+					}
+					for (int i = 0; i < types.length; i++) {
+						System.out.println(resource.getFullPath() + " matched: " + types[i].getId()); //$NON-NLS-1$
+					}
+				}
+			}
+		}
+		return types;
+	}
+
+	/**
+	 * @param resource
+	 * @return
+	 */
+	private IProject getProject(IResource resource) {
+		IProject project = null;
+		if (resource.getType() == IResource.PROJECT) {
+			project = (IProject) resource;
+		}
+		else {
+			project = resource.getProject();
+		}
+		return project;
+	}
+
+	private boolean init(IResource resource) {
+		IProject project = getProject(resource);
+
+		IPreferencesService preferencesService = Platform.getPreferencesService();
+		IScopeContext[] lookupOrder = new IScopeContext[]{new ProjectScope(project), new InstanceScope(), new DefaultScope()};
+
+		boolean proceed = preferencesService.getBoolean(TaskTagPreferenceKeys.TASK_TAG_NODE, TaskTagPreferenceKeys.TASK_TAG_ENABLE, false, lookupOrder);
+
+		if (Logger.DEBUG_TASKSPREFS) {
+			System.out.println(getClass().getName() + " scan of " + resource.getFullPath() + ":" + proceed); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+
+		if (proceed) {
+			String[] tags = StringUtils.unpack(preferencesService.getString(TaskTagPreferenceKeys.TASK_TAG_NODE, TaskTagPreferenceKeys.TASK_TAG_TAGS, null, lookupOrder));
+			String[] priorities = StringUtils.unpack(preferencesService.getString(TaskTagPreferenceKeys.TASK_TAG_NODE, TaskTagPreferenceKeys.TASK_TAG_PRIORITIES, null, lookupOrder));
+			String[] currentIgnoreContentTypeIDs = StringUtils.unpack(preferencesService.getString(TaskTagPreferenceKeys.TASK_TAG_NODE, TaskTagPreferenceKeys.TASK_TAG_CONTENTTYPES_IGNORED, null, lookupOrder));
+			if (Logger.DEBUG_TASKSPREFS) {
+				System.out.print(getClass().getName() + " tags: "); //$NON-NLS-1$
+				for (int i = 0; i < tags.length; i++) {
+					if (i > 0) {
+						System.out.print(","); //$NON-NLS-1$
+					}
+					System.out.print(tags[i]);
+				}
+				System.out.println();
+				System.out.print(getClass().getName() + " priorities: "); //$NON-NLS-1$
+				for (int i = 0; i < priorities.length; i++) {
+					if (i > 0) {
+						System.out.print(","); //$NON-NLS-1$
+					}
+					System.out.print(priorities[i]);
+				}
+				System.out.println();
+				System.out.print(getClass().getName() + " ignored content types: "); //$NON-NLS-1$
+				for (int i = 0; i < currentIgnoreContentTypeIDs.length; i++) {
+					if (i > 0) {
+						System.out.print(","); //$NON-NLS-1$
+					}
+					System.out.print(currentIgnoreContentTypeIDs[i]);
+				}
+				System.out.println();
+			}
+			fCurrentIgnoreContentTypes = new IContentType[currentIgnoreContentTypeIDs.length];
+			IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
+			for (int i = 0; i < currentIgnoreContentTypeIDs.length; i++) {
+				fCurrentIgnoreContentTypes[i] = contentTypeManager.getContentType(currentIgnoreContentTypeIDs[i]);
+			}
+			int max = Math.min(tags.length, priorities.length);
+			fCurrentTaskTags = new TaskTag[max];
+			for (int i = 0; i < max; i++) {
+				int priority = TaskTag.PRIORITY_NORMAL;
+				try {
+					priority = Integer.parseInt(priorities[i]);
+				}
+				catch (NumberFormatException e) {
+					// default to normal priority
+				}
+				fCurrentTaskTags[i] = new TaskTag(tags[i], priority);
+			}
+		}
+		return proceed;
+	}
+
+	void internalScan(final IProject project, final IResource resource, final IProgressMonitor scanMonitor) {
+		if (scanMonitor.isCanceled())
+			return;
+		try {
+			String name = resource.getName();
+			if (resource.isAccessible() && !resource.isDerived() && !resource.isPhantom() && !resource.isTeamPrivateMember() && name.length() != 0 && name.charAt(0) != '.') {
+				if ((resource.getType() & IResource.FOLDER) > 0 || (resource.getType() & IResource.PROJECT) > 0) {
+					IResource[] children = ((IContainer) resource).members();
+					scanMonitor.beginTask("", children.length); //$NON-NLS-1$
+					for (int i = 0; i < children.length; i++) {
+						internalScan(project, children[i], new SubProgressMonitor(scanMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
+					}
+					scanMonitor.done();
+				}
+				else if ((resource.getType() & IResource.FILE) > 0) {
+					scanFile(project, fCurrentTaskTags, (IFile) resource, scanMonitor);
+				}
+			}
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+		}
+	}
+
+	void internalScan(IResourceDelta delta, final IProgressMonitor monitor) {
+		if (monitor.isCanceled())
+			return;
+		try {
+			String name = delta.getFullPath().lastSegment();
+			IResource resource = delta.getResource();
+			if (!resource.isDerived() && !resource.isPhantom() && !resource.isTeamPrivateMember() && name.length() != 0 && name.charAt(0) != '.') {
+				if ((resource.getType() & IResource.FOLDER) > 0 || (resource.getType() & IResource.PROJECT) > 0) {
+					IResourceDelta[] children = delta.getAffectedChildren();
+					monitor.beginTask("", children.length);
+					if (name.length() != 0 && name.charAt(0) != '.' && children.length > 0) {
+						for (int i = children.length - 1; i >= 0; i--) {
+							internalScan(children[i], new SubProgressMonitor(monitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
+						}
+					}
+					monitor.done();
+				}
+				else if ((resource.getType() & IResource.FILE) > 0) {
+					if ((delta.getKind() & IResourceDelta.ADDED) > 0 || ((delta.getKind() & IResourceDelta.CHANGED) > 0 && (delta.getFlags() & IResourceDelta.CONTENT) > 0)) {
+						IFile file = (IFile) resource;
+						scanFile(file.getProject(), fCurrentTaskTags, file, monitor);
+					}
+				}
+			}
+		}
+		catch (Exception e) {
+			Logger.logException(e);
+		}
+	}
+
+	private void replaceTaskMarkers(final IFile file, final String[] markerTypes, final Map markerAttributeMaps[], IProgressMonitor monitor) {
+		final IFile finalFile = file;
+		if (file.isAccessible()) {
+			try {
+				IWorkspaceRunnable r = new IWorkspaceRunnable() {
+					public void run(IProgressMonitor progressMonitor) throws CoreException {
+						progressMonitor.beginTask("", 2);//$NON-NLS-1$
+						try {
+							/*
+							 * Delete old Task markers (don't delete regular
+							 * Tasks since that includes user-defined ones)
+							 */
+							for (int i = 0; i < markerTypes.length; i++) {
+								if (IMarker.TASK.equals(markerTypes[i])) {
+									// only remove if synthetic
+									IMarker[] foundMarkers = file.findMarkers(markerTypes[i], true, IResource.DEPTH_ZERO);
+									for (int j = 0; j < foundMarkers.length; j++) {
+										if (foundMarkers[j].getAttribute(SYNTHETIC_TASK) != null) {
+											foundMarkers[j].delete();
+										}
+									}
+								}
+								else {
+									file.deleteMarkers(markerTypes[i], true, IResource.DEPTH_ZERO);
+								}
+							}
+						}
+						catch (CoreException e) {
+							Logger.logException("exception deleting old tasks", e); //$NON-NLS-1$ 
+						}
+						finally {
+							progressMonitor.worked(1);
+						}
+						if (proceed && markerAttributeMaps != null && markerAttributeMaps.length > 0) {
+							if (Logger.DEBUG_TASKS) {
+								System.out.println("" + markerAttributeMaps.length + " tasks for " + file.getFullPath()); //$NON-NLS-1$ //$NON-NLS-2$
+							}
+							for (int i = 0; i < markerAttributeMaps.length; i++) {
+								String specifiedMarkerType = (String) markerAttributeMaps[i].get(IMarker.TASK);
+								IMarker marker = finalFile.createMarker(specifiedMarkerType);
+								marker.setAttributes(markerAttributeMaps[i]);
+								marker.setAttribute(IMarker.USER_EDITABLE, Boolean.FALSE);
+								marker.setAttribute(MODIFICATION_STAMP, Long.toString(file.getModificationStamp()));
+								if (IMarker.TASK.equals(specifiedMarkerType)) {
+									// set to synthetic and make user editable
+									marker.setAttribute(SYNTHETIC_TASK, true);
+								}
+							}
+						}
+						progressMonitor.worked(1);
+						progressMonitor.done();
+					}
+				};
+				if (file.isAccessible()) {
+					finalFile.getWorkspace().run(r, ResourcesPlugin.getWorkspace().getRuleFactory().modifyRule(file), IWorkspace.AVOID_UPDATE, monitor);
+				}
+			}
+			catch (CoreException e1) {
+				Logger.logException(e1);
+			}
+			catch(OperationCanceledException e) {
+				// not an error condition
+			}
+		}
+	}
+
+	void scan(final IProject project, final IProgressMonitor scanMonitor) {
+		if (scanMonitor.isCanceled())
+			return;
+		if (Logger.DEBUG_TASKS) {
+			System.out.println(getClass().getName() + " scanning project " + project.getName()); //$NON-NLS-1$
+		}
+		if (!project.isAccessible()) {
+			if (Logger.DEBUG_TASKS) {
+				System.out.println(getClass().getName() + " skipping inaccessible project " + project.getName()); //$NON-NLS-1$
+			}
+			return;
+		}
+
+		if (Logger.DEBUG_TASKSOVERALLPERF) {
+			time0 = System.currentTimeMillis();
+		}
+		proceed = init(project);
+		internalScan(project, project, scanMonitor);
+		shutdownDelegates(project);
+		
+		if (Logger.DEBUG_TASKSOVERALLPERF) {
+			System.out.println("" + (System.currentTimeMillis() - time0) + "ms for " + project.getFullPath()); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+
+
+	void scan(IResourceDelta delta, final IProgressMonitor monitor) {
+		if (monitor.isCanceled())
+			return;
+		if (Logger.DEBUG_TASKSOVERALLPERF) {
+			time0 = System.currentTimeMillis();
+		}
+		if (init(delta.getResource())) {
+			internalScan(delta, monitor);
+			shutdownDelegates(delta.getResource().getProject());
+		}
+		if (Logger.DEBUG_TASKSOVERALLPERF) {
+			System.out.println("" + (System.currentTimeMillis() - time0) + "ms for " + delta.getFullPath()); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+
+	void scanFile(IProject project, TaskTag[] taskTags, IFile file, IProgressMonitor monitor) {
+		if (monitor.isCanceled())
+			return;
+
+		// 3 "stages"
+		monitor.beginTask("", 8);//$NON-NLS-1$
+		monitor.subTask(file.getFullPath().toString().substring(1));
+
+		final List markerAttributes = new ArrayList();
+		IContentType[] types = detectContentTypes(file);
+		Set markerTypes = new HashSet(3);
+		// Always included for safety and migration
+		markerTypes.add(DEFAULT_MARKER_TYPE);
+		monitor.worked(1);
+
+		IFileTaskScanner[] fileScanners = null;
+		IFileTaskScanner[] ignoredFileScanners = null;
+		if (types != null) {
+			if (fCurrentIgnoreContentTypes.length == 0) {
+				fileScanners = registry.getFileTaskScanners(types);
+			}
+			else {
+				List validTypes = new ArrayList();
+				// obtain a filtered list of delegates
+				for (int i = 0; i < types.length; i++) {
+					boolean ignoreContentType = false;
+					for (int j = 0; j < fCurrentIgnoreContentTypes.length; j++) {
+						ignoreContentType = ignoreContentType || types[i].isKindOf(fCurrentIgnoreContentTypes[j]);
+					}
+					if (!ignoreContentType) {
+						validTypes.add(types[i]);
+					}
+					else {
+						ignoredFileScanners = registry.getFileTaskScanners(new IContentType[] {types[i]});
+					}
+				}
+				fileScanners = registry.getFileTaskScanners((IContentType[]) validTypes.toArray(new IContentType[validTypes.size()]));
+			}
+			monitor.worked(1);
+			if (ignoredFileScanners != null && ignoredFileScanners.length > 0) {
+				for (int i = 0; i < ignoredFileScanners.length; i++)
+					markerTypes.add(ignoredFileScanners[i].getMarkerType());
+			}
+
+			if (fileScanners.length > 0) {
+				IProgressMonitor scannerMonitor = new SubProgressMonitor(monitor, 3, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+				scannerMonitor.beginTask("", fileScanners.length); //$NON-NLS-1$
+				for (int j = 0; fileScanners != null && j < fileScanners.length; j++) {
+					if (monitor.isCanceled())
+						continue;
+					try {
+						if (!fActiveScanners.contains(fileScanners[j]) && !monitor.isCanceled()) {
+							fileScanners[j].startup(file.getProject());
+							fActiveScanners.add(fileScanners[j]);
+						}
+						markerTypes.add(fileScanners[j].getMarkerType());
+						Map[] taskMarkerAttributes = fileScanners[j].scan(file, taskTags, new SubProgressMonitor(scannerMonitor, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
+						/*
+						 * TODO: pool the marker results so there's only one
+						 * operation creating them
+						 */
+						for (int i = 0; i < taskMarkerAttributes.length; i++) {
+							if (!taskMarkerAttributes[i].containsKey(IMarker.TASK)) {
+								taskMarkerAttributes[i].put(IMarker.TASK, fileScanners[j].getMarkerType());
+							}
+							taskMarkerAttributes[i].put(IMarker.SOURCE_ID, fileScanners[j].getClass().getName());
+							markerAttributes.add(taskMarkerAttributes[i]);
+						}
+					}
+					catch (Exception e) {
+						Logger.logException(file.getFullPath().toString(), e);
+					}
+				}
+				scannerMonitor.done();
+			}
+		}
+		else {
+			monitor.worked(4);
+		}
+
+		if (monitor.isCanceled())
+			return;
+		// only update markers if we ran a scanner on this file
+		if (fileScanners != null && fileScanners.length > 0 ||
+				ignoredFileScanners != null && ignoredFileScanners.length > 0) {
+			IProgressMonitor markerUpdateMonitor = new SubProgressMonitor(monitor, 3, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+			if (markerAttributes != null)
+			replaceTaskMarkers(file, (String[]) markerTypes.toArray(new String[markerTypes.size()]), (Map[]) markerAttributes.toArray(new Map[markerAttributes.size()]), markerUpdateMonitor);
+		}
+		else {
+			monitor.worked(3);
+		}
+		monitor.done();
+	}
+
+	private void shutdownDelegates(IProject project) {
+		for (int j = 0; j < fActiveScanners.size(); j++) {
+			try {
+				((IFileTaskScanner) fActiveScanners.get(j)).shutdown(project);
+			}
+			catch (Exception e) {
+				Logger.logException(project.getFullPath().toString(), e);
+			}
+		}
+		fActiveScanners = new ArrayList(1);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/StructuredModelManager.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/StructuredModelManager.java
new file mode 100644
index 0000000..ecb0ece
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/StructuredModelManager.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 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.wst.sse.core;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.sse.core.internal.SSECorePlugin;
+import org.eclipse.wst.sse.core.internal.model.ModelManagerImpl;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.osgi.framework.Bundle;
+
+/**
+ * Class to allow access to properly configured implementors of IModelManager.
+ * 
+ * @since  1.5  org.eclipse.wst.sse.core
+ */
+final public class StructuredModelManager {
+	/**
+	 * Do not allow instances to be created.
+	 */
+	private StructuredModelManager() {
+		super();
+	}
+
+	/**
+	 * Provides access to the instance of IModelManager. Returns null if model
+	 * manager can not be created or is not valid (such as, when workbench is
+	 * shutting down).
+	 * 
+	 * @return IModelManager - returns the one model manager for structured
+	 *         models or null if the owning bundle is neither active nor
+	 *         starting.
+	 */
+	public static IModelManager getModelManager() {
+		boolean isReady = false;
+		IModelManager modelManager = null;
+		boolean interrupted = false;
+		try {
+			while (!isReady) {
+				Bundle localBundle = Platform.getBundle(SSECorePlugin.ID);
+				int state = localBundle.getState();
+				if (state == Bundle.ACTIVE) {
+					isReady = true;
+					// getInstance is a synchronized static method.
+					modelManager = ModelManagerImpl.getInstance();
+				}
+				else if (state == Bundle.STARTING) {
+					try {
+						Thread.sleep(100);
+					}
+					catch (InterruptedException e) {
+						// ignore, just loop again
+						interrupted = true;
+					}
+				}
+				else if (state == Bundle.STOPPING || state == Bundle.UNINSTALLED) {
+					isReady = true;
+					modelManager = null;
+				}
+				else {
+					// not sure about other states, 'resolved', 'installed'
+					isReady = true;
+					modelManager = null;
+				}
+			}
+		}
+		finally {
+			if (interrupted) {
+				Thread.currentThread().interrupt();
+			}
+		}
+		return modelManager;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/indexing/AbstractIndexManager.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/indexing/AbstractIndexManager.java
new file mode 100644
index 0000000..f553b58
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/indexing/AbstractIndexManager.java
@@ -0,0 +1,1990 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 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.wst.sse.core.indexing;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IResourceProxy;
+import org.eclipse.core.resources.IResourceProxyVisitor;
+import org.eclipse.core.resources.ISaveParticipant;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.SSECoreMessages;
+
+/**
+ * <p>
+ * A generic class for implementing a resource index manager. It is important
+ * to note that this only provides the framework for managing an index, not
+ * actually indexing. The subtle difference is that the manager is in charge
+ * of paying attention to all of the resource actions that take place in the
+ * workspace and filtering those actions down to simple actions that need to
+ * be performed on whatever index this manager is managing.
+ * </p>
+ * 
+ * <p>
+ * The manager does its very best to make sure the index is always consistent,
+ * even if resource events take place when the manager is not running. In the
+ * event that the manager determines it has missed, lost, or corrupted any
+ * resource change events that have occurred before, during, or after its
+ * activation or deactivation then the manager will inspect the entire
+ * workspace to insure the index it is managing is consistent.
+ * </p>
+ * 
+ */
+public abstract class AbstractIndexManager {
+
+	/** Used to encode path bytes in case they contain double byte characters */
+	private static final String ENCODING_UTF16 = "utf16"; //$NON-NLS-1$
+
+	/** Default time to wait for other tasks to finish */
+	private static final int WAIT_TIME = 300;
+
+	/**
+	 * <p>
+	 * Used to report progress on jobs where the total work to complete is
+	 * unknown. The created effect is a progress bar that moves but that will
+	 * never complete.
+	 * </p>
+	 */
+	private static final int UNKNOWN_WORK = 100;
+
+	/**
+	 * The amount of events to batch up before sending them off to the
+	 * processing job
+	 */
+	private static final int BATCH_UP_AMOUNT = 100;
+
+	/** If this file exists then a full workspace re-processing is needed */
+	private static final String RE_PROCESS_FILE_NAME = ".re-process"; //$NON-NLS-1$
+
+	/** Common error message to log */
+	private static final String LOG_ERROR_INDEX_INVALID = "Index may become invalid, incomplete, or enter some other inconsistent state."; //$NON-NLS-1$
+
+	/** State: manager is stopped */
+	private static final byte STATE_DISABLED = 0;
+
+	/** State: manager is running */
+	private static final byte STATE_ENABLED = 1;
+
+	/** Action: add to index */
+	protected static final byte ACTION_ADD = 0;
+
+	/** Action: remove from index */
+	protected static final byte ACTION_REMOVE = 1;
+
+	/** Action: add to index caused by move operation */
+	protected static final byte ACTION_ADD_MOVE_FROM = 2;
+
+	/** Action: remove from index caused by move operation */
+	protected static final byte ACTION_REMOVE_MOVE_TO = 3;
+
+	/** Source: action originated from resource change event */
+	protected static final byte SOURCE_RESOURCE_CHANGE = 0;
+
+	/** Source: action originated from workspace scan */
+	protected static final byte SOURCE_WORKSPACE_SCAN = 1;
+
+	/** Source: action originated from saved state */
+	protected static final byte SOURCE_SAVED_STATE = 2;
+
+	/** Source: preserved resources to index */
+	protected static final byte SOURCE_PRESERVED_RESOURCES_TO_INDEX = 3;
+
+	/** the name of this index manager */
+	private String fName;
+
+	/** {@link IResourceChangeListener} to listen for file changes */
+	private ResourceChangeListener fResourceChangeListener;
+
+	/** The {@link Job} that does all of the indexing */
+	private ResourceEventProcessingJob fResourceEventProcessingJob;
+
+	/** A {@link Job} to search the workspace for all files */
+	private Job fWorkspaceVisitorJob;
+
+	/**
+	 * <p>
+	 * Current state of the manager
+	 * </p>
+	 * 
+	 * @see #STATE_DISABLED
+	 * @see #STATE_ENABLED
+	 */
+	private volatile byte fState;
+
+	/** used to prevent manager from starting and stopping at the same time */
+	private Object fStartStopLock = new Object();
+
+	/**
+	 * <code>true</code> if the manager is currently starting,
+	 * <code>false</code> otherwise
+	 */
+	private boolean fStarting;
+
+	/**
+	 * <p>
+	 * Creates the manager with a given name.
+	 * </p>
+	 * 
+	 * @param name
+	 *            This will be pre-pended to progress reporting messages and
+	 *            thus should be translated
+	 */
+	protected AbstractIndexManager(String name) {
+		this.fName = name;
+		this.fState = STATE_DISABLED;
+		this.fResourceChangeListener = new ResourceChangeListener();
+		this.fResourceEventProcessingJob = new ResourceEventProcessingJob();
+		this.fStarting = false;
+	}
+
+	/**
+	 * <p>
+	 * Creates the manager with a given name.
+	 * </p>
+	 * 
+	 * @param name
+	 *            This will be pre-pended to progress reporting messages and
+	 *            thus should be translated
+	 * 
+	 * @param messageRunning
+	 *            ignored
+	 * @param messageInitializing
+	 *            ignored
+	 * @param messageProcessingFiles
+	 *            ignored
+	 * 
+	 * @deprecated This constructor ignores the last three parameters.
+	 * @see #AbstractIndexManager(String)
+	 */
+
+	protected AbstractIndexManager(String name, String messageRunning, String messageInitializing, String messageProcessingFiles) {
+		this(name);
+	}
+
+	/**
+	 * <p>
+	 * Starts up the {@link AbstractIndexManager}. If a {@link IResourceDelta}
+	 * is provided then it is assumed that all other files in the workspace
+	 * have already been index and thus only those in the provided
+	 * {@link IResourceDelta} will be processed. Else if the provided
+	 * {@link IResourceDelta} is <code>null</code> it is assumed no files have
+	 * been indexed yet so the entire workspace will be searched for files to
+	 * be indexed.
+	 * </p>
+	 * 
+	 * <p>
+	 * If {@link IResourceDelta} is provided this will block until that delta
+	 * has finished processing. If no {@link IResourceDelta} provided then a
+	 * separate job will be created to process the entire workspace and this
+	 * method will return without waiting for that job to complete
+	 * </p>
+	 * 
+	 * <p>
+	 * Will block until {@link #stop()} has finished running if it is
+	 * currently running
+	 * </p>
+	 * 
+	 * @param savedStateDelta
+	 *            the delta from a saved state, if <code>null</code> then the
+	 *            entire workspace will be searched for files to index, else
+	 *            only files in this {@link IResourceDelta} will be indexed
+	 * @param monitor
+	 *            This action can not be canceled but this monitor will be
+	 *            used to report progress
+	 */
+	public final void start(IResourceDelta savedStateDelta, IProgressMonitor monitor) {
+		SubMonitor progress = SubMonitor.convert(monitor);
+		synchronized (this.fStartStopLock) {
+			this.fStarting = true;
+
+			try {
+				if (this.fState == STATE_DISABLED) {
+					// report status
+					progress.beginTask(NLS.bind(SSECoreMessages.IndexManager_0_starting, this.fName), 2);
+
+					// start listening for resource change events
+					this.fResourceChangeListener.start();
+
+					// check to see if a full re-index is required
+					boolean forcedFullReIndexNeeded = this.isForcedFullReIndexNeeded();
+
+					/*
+					 * start the indexing job only loading preserved state if
+					 * not doing full index if failed loading preserved state
+					 * then force full re-index
+					 */
+					forcedFullReIndexNeeded = !this.fResourceEventProcessingJob.start(!forcedFullReIndexNeeded, progress.newChild(1));
+					progress.setWorkRemaining(1);
+
+					// don't bother processing saved delta if forced full
+					// re-index is needed
+					if (!forcedFullReIndexNeeded) {
+						/*
+						 * if there is a delta attempt to process it else need
+						 * to do a full workspace index
+						 */
+						if (savedStateDelta != null) {
+							forcedFullReIndexNeeded = false;
+							try {
+								// deal with reporting progress
+								SubMonitor savedStateProgress = progress.newChild(1, SubMonitor.SUPPRESS_NONE);
+
+								savedStateProgress.setTaskName(NLS.bind(SSECoreMessages.IndexManager_0_starting_1, new String[]{this.fName, SSECoreMessages.IndexManager_processing_deferred_resource_changes}));
+
+								// process delta
+								ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(savedStateProgress, AbstractIndexManager.SOURCE_SAVED_STATE);
+								savedStateDelta.accept(visitor);
+
+								// process any remaining batched up resources
+								// to index
+								visitor.processBatchedResourceEvents();
+							}
+							catch (CoreException e) {
+								forcedFullReIndexNeeded = true;
+								Logger.logException(this.fName + ": Could not process saved state. " + //$NON-NLS-1$
+											"Forced to do a full workspace re-index.", e); //$NON-NLS-1$
+							}
+						}
+						else {
+							forcedFullReIndexNeeded = true;
+						}
+					}
+					progress.worked(1);
+
+					// if need to process the entire workspace do so in
+					// another job
+					if (forcedFullReIndexNeeded) {
+						this.fWorkspaceVisitorJob = new WorkspaceVisitorJob();
+						this.fWorkspaceVisitorJob.schedule();
+					}
+
+					// update state
+					this.fState = STATE_ENABLED;
+				}
+			}
+			finally {
+				this.fStarting = false;
+				progress.done();
+			}
+		}
+	}
+
+	/**
+	 * <p>
+	 * Safely shuts down the manager.
+	 * </p>
+	 * 
+	 * <p>
+	 * This will block until the
+	 * {@link #start(IResourceDelta, IProgressMonitor)} has finished (if
+	 * running). Also until the current resource event has finished being
+	 * processed. Finally it will block until the events still to be processed
+	 * by the processing job have been preserved to be processed on the next
+	 * call to {@link #start(IResourceDelta, IProgressMonitor)}.
+	 * </p>
+	 * 
+	 * <p>
+	 * If at any point during this shut down processes something goes wrong
+	 * the manager will be sure that on the next call to
+	 * {@link #start(IResourceDelta, IProgressMonitor)} the entire workspace
+	 * will be re-processed.
+	 * </p>
+	 * 
+	 * @throws InterruptedException
+	 */
+	public final void stop() throws InterruptedException {
+		synchronized (this.fStartStopLock) {
+			if (this.fState != STATE_DISABLED) {
+
+				// stop listening for events, and wait for the current event
+				// to finish
+				this.fResourceChangeListener.stop();
+
+				// if currently visiting entire workspace, give up and try
+				// again next load
+				boolean forceFullReIndexNextStart = false;
+				if (this.fWorkspaceVisitorJob != null) {
+					if (this.fWorkspaceVisitorJob.getState() != Job.NONE) {
+						this.fWorkspaceVisitorJob.cancel();
+
+						this.forceFullReIndexNextStart();
+						forceFullReIndexNextStart = true;
+					}
+				}
+
+				// stop the indexing job, only preserve if not already forcing
+				// a re-index
+				forceFullReIndexNextStart = !this.fResourceEventProcessingJob.stop(!forceFullReIndexNextStart);
+
+				// if preserving failed, then force re-index
+				if (forceFullReIndexNextStart) {
+					this.forceFullReIndexNextStart();
+				}
+
+				// update status
+				this.fState = STATE_DISABLED;
+			}
+		}
+	}
+
+	/**
+	 * @return the name of this indexer
+	 */
+	protected String getName() {
+		return this.fName;
+	}
+
+	/**
+	 * <p>
+	 * Should be called by a client of the index this manager manages before
+	 * the index is accessed, assuming the client wants an index consistent
+	 * with the latest resource changes.
+	 * </p>
+	 * 
+	 * <p>
+	 * The supplied monitor will be used to supply user readable progress as
+	 * the manager insures the index has been given all the latest resource
+	 * events. This monitor may be canceled, but if it is the state of the
+	 * index is not guaranteed to be consistent with the latest resource
+	 * change events.
+	 * </p>
+	 * 
+	 * @param monitor
+	 *            Used to report user readable progress as the manager insures
+	 *            the index is consistent with the latest resource events.
+	 *            This monitor can be canceled to stop waiting for consistency
+	 *            but then no guaranty is made about the consistency of the
+	 *            index in relation to unprocessed resource changes
+	 * 
+	 * @return <code>true</code> if the wait finished successfully and the
+	 *         manager is consistent, <code>false</code> otherwise, either an
+	 *         error occurred while waiting for the manager or the monitor was
+	 *         canceled
+	 * 
+	 * @throws InterruptedException
+	 *             This can happen when waiting for other jobs
+	 */
+	public final boolean waitForConsistent(IProgressMonitor monitor) {
+		boolean success = true;
+		boolean interupted = false;
+		SubMonitor progress = SubMonitor.convert(monitor);
+
+		// set up the progress of waiting
+		int remainingWork = 4;
+		progress.beginTask(NLS.bind(SSECoreMessages.IndexManager_Waiting_for_0, this.fName), remainingWork);
+
+		// wait for start up
+		if (this.fStarting && !monitor.isCanceled()) {
+			SubMonitor startingProgress = progress.newChild(1);
+			startingProgress.subTask(NLS.bind(SSECoreMessages.IndexManager_0_starting, this.fName));
+			while (this.fStarting && !monitor.isCanceled()) {
+				// this creates a never ending progress that still moves
+				// forward
+				startingProgress.setWorkRemaining(UNKNOWN_WORK);
+				startingProgress.newChild(1).worked(1);
+				try {
+					Thread.sleep(WAIT_TIME);
+				}
+				catch (InterruptedException e) {
+					interupted = true;
+				}
+			}
+		}
+		progress.setWorkRemaining(--remainingWork);
+
+		// wait for workspace visiting job
+		if (this.fWorkspaceVisitorJob != null && this.fWorkspaceVisitorJob.getState() != Job.NONE && !monitor.isCanceled()) {
+			SubMonitor workspaceVisitorProgress = progress.newChild(1);
+			workspaceVisitorProgress.subTask(SSECoreMessages.IndexManager_Processing_entire_workspace_for_the_first_time);
+			while (this.fWorkspaceVisitorJob.getState() != Job.NONE && !monitor.isCanceled()) {
+				// this creates a never ending progress that still moves
+				// forward
+				workspaceVisitorProgress.setWorkRemaining(UNKNOWN_WORK);
+				workspaceVisitorProgress.newChild(1).worked(1);
+				try {
+					Thread.sleep(WAIT_TIME);
+				}
+				catch (InterruptedException e) {
+					interupted = true;
+				}
+			}
+		}
+		progress.setWorkRemaining(--remainingWork);
+
+		// wait for the current resource event
+		if (this.fResourceChangeListener.isProcessingEvents() && !monitor.isCanceled()) {
+			SubMonitor workspaceVisitorProgress = progress.newChild(1);
+			workspaceVisitorProgress.subTask(SSECoreMessages.IndexManager_processing_recent_resource_changes);
+			while (this.fResourceChangeListener.isProcessingEvents() && !monitor.isCanceled()) {
+				workspaceVisitorProgress.setWorkRemaining(UNKNOWN_WORK);
+				workspaceVisitorProgress.newChild(1).worked(1);
+				try {
+					this.fResourceChangeListener.waitForCurrentEvent(WAIT_TIME);
+				}
+				catch (InterruptedException e) {
+					interupted = true;
+				}
+			}
+		}
+		progress.setWorkRemaining(--remainingWork);
+
+		// wait for all files to be indexed
+		if (this.fResourceEventProcessingJob.getNumResourceEventsToProcess() != 0 && !monitor.isCanceled()) {
+			SubMonitor indexingProgress = progress.newChild(1);
+			int prevNumResources;
+			int numResources = this.fResourceEventProcessingJob.getNumResourceEventsToProcess();
+			while (numResources != 0 && !monitor.isCanceled()) {
+				// update the progress indicator
+				indexingProgress.subTask(NLS.bind(SSECoreMessages.IndexManager_0_Indexing_1_Files, new Object[]{AbstractIndexManager.this.fName, "" + numResources})); //$NON-NLS-1$
+				indexingProgress.setWorkRemaining(numResources);
+				prevNumResources = numResources;
+				numResources = this.fResourceEventProcessingJob.getNumResourceEventsToProcess();
+				int numProcessed = prevNumResources - numResources;
+				indexingProgress.worked(numProcessed > 0 ? numProcessed : 0);
+
+				// give the index some time to do some indexing
+				try {
+					this.fResourceEventProcessingJob.waitForConsistant(WAIT_TIME);
+				}
+				catch (InterruptedException e) {
+					interupted = true;
+				}
+			}
+		}
+		progress.setWorkRemaining(--remainingWork);
+
+		if (monitor.isCanceled()) {
+			success = false;
+		}
+
+		// reset the interrupted flag if we were interrupted
+		if (interupted) {
+			Thread.currentThread().interrupt();
+		}
+
+		progress.done();
+		return success;
+	}
+
+	/**
+	 * <p>
+	 * Called for each {@link IResource} given in a resource delta. If the
+	 * resource type is a file then used to determine if that file should be
+	 * processed by the manager, if the resource type is a project or
+	 * directory then it is used to determine if the children of the project
+	 * or directory should be processed looking for file resources.
+	 * </p>
+	 * 
+	 * <p>
+	 * <b>NOTE:</b> Even if <code>true</code> is returned for a directory
+	 * resource that only means the children of the directory should be
+	 * inspected for possible files to index. Directories themselves can not
+	 * be managed in order to add to an index.
+	 * </p>
+	 * 
+	 * @param type
+	 *            the {@link IResource#getType()} result of the resource to
+	 *            possibly index
+	 * @param path
+	 *            the full {@link IPath} to the resource to possibly index
+	 * @return <code>true</code> If the resource with the given
+	 *         <code>type</code> and <code>path</code> should either itself be
+	 *         indexed, or its children should be indexed, <code>false</code>
+	 *         if neither the described resource or any children should be
+	 *         indexed
+	 */
+	protected abstract boolean isResourceToIndex(int type, IPath path);
+
+	/**
+	 * <p>
+	 * Called for each {@link ResourceEvent} gathered by the various sources
+	 * and processed by the {@link ResourceEventProcessingJob}. The
+	 * implementation of this method should use the given information to
+	 * update the index this manager is managing.
+	 * </p>
+	 * 
+	 * @param source
+	 *            The source that reported this resource event
+	 * @param action
+	 *            The action to be taken on the given <code>resource</code>
+	 * @param resource
+	 *            The index should perform the given <code>action</code> on
+	 *            this resource
+	 * @param movePath
+	 *            If the given <code>action</code> is
+	 *            {@link AbstractIndexManager#ACTION_ADD_MOVE_FROM} or
+	 *            {@link AbstractIndexManager#ACTION_REMOVE_MOVE_TO} then this
+	 *            field will not be null and reports the path the given
+	 *            <code>resource</code> was either moved from or moved to
+	 *            respectively.
+	 * 
+	 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
+	 * @see AbstractIndexManager#SOURCE_SAVED_STATE
+	 * @see AbstractIndexManager#SOURCE_WORKSPACE_SCAN
+	 * @see AbstractIndexManager#SOURCE_PRESERVED_RESOURCES_TO_INDEX
+	 * 
+	 * @see AbstractIndexManager#ACTION_ADD
+	 * @see AbstractIndexManager#ACTION_REMOVE
+	 * @see AbstractIndexManager#ACTION_ADD_MOVE_FROM
+	 * @see AbstractIndexManager#ACTION_REMOVE_MOVE_TO
+	 */
+	protected abstract void performAction(byte source, byte action, IResource resource, IPath movePath);
+
+	/**
+	 * <p>
+	 * Gets the working location of the manager. This is where any relevant
+	 * state can be persisted.
+	 * </p>
+	 * 
+	 * @return the working location of the manager
+	 */
+	protected abstract IPath getWorkingLocation();
+
+	/**
+	 * <p>
+	 * Next time the manager starts up force a full workspace index
+	 * </p>
+	 */
+	private void forceFullReIndexNextStart() {
+		IPath reIndexPath = AbstractIndexManager.this.getWorkingLocation().append(RE_PROCESS_FILE_NAME);
+		File file = new File(reIndexPath.toOSString());
+		try {
+			file.createNewFile();
+		}
+		catch (IOException e) {
+			Logger.logException(this.fName + ": Could not create file to tell manager to" + " do a full re-index on next load. " + AbstractIndexManager.LOG_ERROR_INDEX_INVALID, e); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+
+	/**
+	 * @return <code>true</code> if a full workspace index is needed as
+	 *         dictated by a previous call to
+	 *         {@link #forceFullReIndexNextStart()}, <code>false</code>
+	 *         otherwise
+	 */
+	private boolean isForcedFullReIndexNeeded() {
+		boolean forcedFullReIndexNeeded = false;
+		IPath reIndexPath = AbstractIndexManager.this.getWorkingLocation().append(RE_PROCESS_FILE_NAME);
+		File file = new File(reIndexPath.toOSString());
+		if (file.exists()) {
+			forcedFullReIndexNeeded = true;
+			file.delete();
+		}
+
+		return forcedFullReIndexNeeded;
+	}
+
+	/**
+	 * <p>
+	 * A system {@link Job} used to visit all of the files in the workspace
+	 * looking for files to index.
+	 * </p>
+	 * 
+	 * <p>
+	 * This should only have to be done once per workspace on the first load,
+	 * but if it fails or a SavedState can not be retrieved on a subsequent
+	 * workspace load then this will have to be done again.
+	 * </p>
+	 */
+	private class WorkspaceVisitorJob extends Job {
+		/**
+		 * <p>
+		 * Default constructor that sets up this job as a system job
+		 * </p>
+		 */
+		protected WorkspaceVisitorJob() {
+			super(NLS.bind(SSECoreMessages.IndexManager_0_Processing_entire_workspace_for_the_first_time, AbstractIndexManager.this.fName));
+
+			this.setUser(false);
+			this.setSystem(true);
+			this.setPriority(Job.LONG);
+		}
+
+		/**
+		 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+		 */
+		protected IStatus run(IProgressMonitor monitor) {
+			try {
+				// update status
+				monitor.beginTask(NLS.bind(SSECoreMessages.IndexManager_0_Processing_entire_workspace_for_the_first_time, AbstractIndexManager.this.fName), IProgressMonitor.UNKNOWN);
+
+				// visit the workspace
+				WorkspaceVisitor visitor = new WorkspaceVisitor(monitor);
+				ResourcesPlugin.getWorkspace().getRoot().accept(visitor, IResource.NONE);
+
+				// process any remaining batched up resources to index
+				visitor.processBatchedResourceEvents();
+			}
+			catch (CoreException e) {
+				Logger.logException(AbstractIndexManager.this.fName + ": Failed visiting entire workspace for initial index. " + AbstractIndexManager.LOG_ERROR_INDEX_INVALID, e); //$NON-NLS-1$
+			}
+
+			IStatus status;
+			if (monitor.isCanceled()) {
+				status = Status.CANCEL_STATUS;
+			}
+			else {
+				status = Status.OK_STATUS;
+			}
+
+			monitor.done();
+			return status;
+		}
+
+		/**
+		 * <p>
+		 * An {@link IResourceProxyVisitor} used to visit all of the files in
+		 * the workspace looking for files to add to the index.
+		 * </p>
+		 * 
+		 * <p>
+		 * <b>NOTE: </b>After this visitor is used
+		 * {@link WorkspaceVisitor#processBatchedResourceEvents() must be
+		 * called to flush out the last of the {@link ResourceEvent}s produced
+		 * by this visitor.
+		 * </p>
+		 */
+		private class WorkspaceVisitor implements IResourceProxyVisitor {
+			/**
+			 * {@link IProgressMonitor} used to report status and check for
+			 * cancellation
+			 */
+			private SubMonitor fProgress;
+
+			/**
+			 * {@link Map}&lt{@link IResource}, {@link ResourceEvent}&gt
+			 * <p>
+			 * Map of resources events created and batched up by this visitor.
+			 * These events are periodical be sent off to the
+			 * {@link ResourceEventProcessingJob} but need to be sent off one
+			 * final time after this visitor finishes it work.
+			 * </p>
+			 * 
+			 * @see #processBatchedResourceEvents()
+			 */
+			private Map fBatchedResourceEvents;
+
+			/**
+			 * <p>
+			 * Default constructor
+			 * </p>
+			 * 
+			 * @param monitor
+			 *            used to report status and allow this visitor to be
+			 *            canceled
+			 */
+			protected WorkspaceVisitor(IProgressMonitor monitor) {
+				this.fProgress = SubMonitor.convert(monitor);
+				this.fBatchedResourceEvents = new LinkedHashMap(BATCH_UP_AMOUNT);
+			}
+
+			/**
+			 * <p>
+			 * As long as the monitor is not canceled visit each file in the
+			 * workspace that should be visited.
+			 * </p>
+			 * 
+			 * @see org.eclipse.core.resources.IResourceProxyVisitor#visit(org.eclipse.core.resources.IResourceProxy)
+			 * @see AbstractIndexManager#shouldVisit(String)
+			 */
+			public boolean visit(IResourceProxy proxy) throws CoreException {
+				this.fProgress.subTask(proxy.getName());
+
+				boolean visitChildren = false;
+
+				/*
+				 * if not canceled or a hidden resource then process file else
+				 * don't visit children
+				 */
+				if (!this.fProgress.isCanceled()) {
+					if (proxy.isDerived()) {
+						/*
+						 * Do not include derived resources
+						 */
+						visitChildren = false;
+					}
+					else if (proxy.requestFullPath().isRoot()) {
+						visitChildren = true;
+					}
+					else if (isResourceToIndex(proxy.getType(), proxy.requestFullPath())) {
+						if (proxy.getType() == IResource.FILE) {
+							// add the file to be indexed
+							IFile file = (IFile) proxy.requestResource();
+							if (file.exists()) {
+								this.fBatchedResourceEvents.put(file, new ResourceEvent(AbstractIndexManager.SOURCE_WORKSPACE_SCAN, AbstractIndexManager.ACTION_ADD, null));
+							}
+						}
+						visitChildren = true;
+					}
+				}
+
+				// batch up resource changes before sending them out
+				if (this.fBatchedResourceEvents.size() >= BATCH_UP_AMOUNT) {
+					this.processBatchedResourceEvents();
+				}
+
+				return visitChildren;
+			}
+
+			/**
+			 * <p>
+			 * Sends any batched up resource events created by this visitor to
+			 * the {@link ResourceEventProcessingJob}.
+			 * <p>
+			 * 
+			 * <p>
+			 * <b>NOTE:</b> This will be called every so often as the visitor
+			 * is visiting resources but needs to be called a final time by
+			 * the user of this visitor to be sure the final events are sent
+			 * off
+			 * </p>
+			 */
+			protected void processBatchedResourceEvents() {
+				AbstractIndexManager.this.fResourceEventProcessingJob.addResourceEvents(this.fBatchedResourceEvents);
+				this.fBatchedResourceEvents.clear();
+			}
+		}
+	}
+
+	/**
+	 * <p>
+	 * Used to listen to resource change events in the workspace. These events
+	 * are batched up and then passed onto the
+	 * {@link ResourceEventProcessingJob}.
+	 * </p>
+	 */
+	private class ResourceChangeListener implements IResourceChangeListener {
+		/**
+		 * <p>
+		 * The number of events currently being processed by this listener.
+		 * </p>
+		 * <p>
+		 * Use the {@link #fEventsBeingProcessedLock} when reading or writing
+		 * this field
+		 * </p>
+		 * 
+		 * @see #fEventsBeingProcessedLock
+		 */
+		private volatile int fEventsBeingProcessed;
+
+		/**
+		 * Lock to use when reading or writing {@link #fEventsBeingProcessed}
+		 * 
+		 * @see #fEventsBeingProcessed
+		 */
+		private final Object fEventsBeingProcessedLock = new Object();
+
+		/**
+		 * <p>
+		 * Current state of this listener
+		 * </p>
+		 * 
+		 * @see AbstractIndexManager#STATE_DISABLED
+		 * @see AbstractIndexManager#STATE_ENABLED
+		 */
+		private volatile byte fState;
+
+		/**
+		 * <p>
+		 * Default constructor
+		 * </p>
+		 */
+		protected ResourceChangeListener() {
+			this.fState = STATE_DISABLED;
+			this.fEventsBeingProcessed = 0;
+		}
+
+		/**
+		 * <p>
+		 * Start listening for resource change events
+		 * </p>
+		 */
+		protected void start() {
+			this.fState = STATE_ENABLED;
+			ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
+		}
+
+		/**
+		 * <p>
+		 * Stop listening for resource change events and if already processing
+		 * an event then wait for that processing to finish
+		 * </p>
+		 * 
+		 * @throws InterruptedException
+		 *             waiting for a current event to finish processing could
+		 *             be interrupted
+		 */
+		protected void stop() throws InterruptedException {
+			ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
+
+			// wait indefinitely for current event to finish processing
+			this.waitForCurrentEvent(0);
+
+			this.fState = STATE_DISABLED;
+		}
+
+		/**
+		 * <p>
+		 * Blocks until either the current resource event has been processed
+		 * or until the given timeout has passed.
+		 * </p>
+		 * 
+		 * @param timeout
+		 *            block until either this timeout elapses (0 means never
+		 *            to timeout) or the current resource change event
+		 *            finishes being processed
+		 * 
+		 * @throws InterruptedException
+		 *             This can happen when waiting for a lock
+		 */
+		protected void waitForCurrentEvent(int timeout) throws InterruptedException {
+			synchronized (this.fEventsBeingProcessedLock) {
+				if (this.fEventsBeingProcessed != 0) {
+					this.fEventsBeingProcessedLock.wait(timeout);
+				}
+			}
+		}
+
+		/**
+		 * @return <code>true</code> if this listener is currently processing
+		 *         any events, <code>false</code> otherwise.
+		 */
+		protected boolean isProcessingEvents() {
+			return this.fEventsBeingProcessed != 0;
+		}
+
+		/**
+		 * <p>
+		 * Process a resource change event. If it is a pre-close or pre-delete
+		 * then the {@link ResourceEventProcessingJob} is paused so it does
+		 * not try to process resources that are about to be deleted. The
+		 * {@link ResourceDeltaVisitor} is used to actually process the event.
+		 * </p>
+		 * 
+		 * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
+		 * @see ResourceDeltaVisitor
+		 */
+		public void resourceChanged(IResourceChangeEvent event) {
+			try {
+				// update the number of events being processed
+				synchronized (this.fEventsBeingProcessedLock) {
+					++this.fEventsBeingProcessed;
+				}
+
+				if (this.fState == STATE_ENABLED) {
+					switch (event.getType()) {
+						case IResourceChangeEvent.PRE_CLOSE :
+						case IResourceChangeEvent.PRE_DELETE : {
+							/*
+							 * pause the persister job so it does not
+							 * interfere
+							 */
+							AbstractIndexManager.this.fResourceEventProcessingJob.pause();
+							break;
+						}
+						case IResourceChangeEvent.POST_BUILD :
+						case IResourceChangeEvent.POST_CHANGE : {
+							// post change start up the indexer job and
+							// process the delta
+							AbstractIndexManager.this.fResourceEventProcessingJob.unPause();
+
+							// only analyze the full (starting at root) delta
+							// hierarchy
+							IResourceDelta delta = event.getDelta();
+							if (delta != null && delta.getFullPath().toString().equals("/")) { //$NON-NLS-1$
+								try {
+									// use visitor to visit all children
+									ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(AbstractIndexManager.SOURCE_RESOURCE_CHANGE);
+									delta.accept(visitor, false);
+
+									// process any remaining batched up
+									// resources to index
+									visitor.processBatchedResourceEvents();
+								}
+								catch (CoreException e) {
+									Logger.logException(AbstractIndexManager.this.fName + ": Failed visiting resource change delta. " + AbstractIndexManager.LOG_ERROR_INDEX_INVALID, e); //$NON-NLS-1$
+								}
+							}
+							break;
+						}
+					}
+				}
+				else {
+					Logger.log(Logger.ERROR, "A resource change event came in after " + //$NON-NLS-1$
+								AbstractIndexManager.this.fName + " shut down. This should never " + //$NON-NLS-1$
+								"ever happen, but if it does the index may now be inconsistant."); //$NON-NLS-1$
+				}
+			}
+			finally {
+				// no matter how we exit be sure to update the number of
+				// events being processed
+				synchronized (this.fEventsBeingProcessedLock) {
+					--this.fEventsBeingProcessed;
+
+					// if currently not events being processed, then notify
+					if (this.fEventsBeingProcessed == 0) {
+						this.fEventsBeingProcessedLock.notifyAll();
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * <p>
+	 * Used to visit {@link IResourceDelta}s from both the
+	 * {@link IResourceChangeListener} and from a {@link ISaveParticipant}
+	 * given to
+	 * {@link AbstractIndexManager#start(IResourceDelta, IProgressMonitor)}.
+	 * The resource events are batched into groups of
+	 * {@link AbstractIndexManager#BATCH_UP_AMOUNT} before being passed onto
+	 * the {@link ResourceEventProcessingJob}.
+	 * </p>
+	 * 
+	 * <p>
+	 * <b>NOTE 1: </b> This class is intended for one time use, thus a new
+	 * instance should be instantiated each time this visitor is needed to
+	 * process a new {@link IResourceDelta}.
+	 * </p>
+	 * 
+	 * <p>
+	 * <b>NOTE 2: </b> Be sure to call
+	 * {@link ResourceDeltaVisitor#processBatchedResourceEvents()} after using
+	 * this visitor to be sure any remaining events get passed onto the
+	 * {@link ResourceEventProcessingJob}.
+	 * </p>
+	 * 
+	 * @see ResourceDeltaVisitor#processBatchedResourceEvents()
+	 */
+	private class ResourceDeltaVisitor implements IResourceDeltaVisitor {
+		/** {@link IProgressMonitor} used to report status */
+		private SubMonitor fProgress;
+
+		/**
+		 * <p>
+		 * The source that should be used when sending resource events to the
+		 * {@link ResourceEventProcessingJob}.
+		 * </p>
+		 * 
+		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
+		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
+		 */
+		private byte fSource;
+
+		/**
+		 * <p>
+		 * Due to the nature of a visitor it has no way of knowing the total
+		 * amount of work it has to do but it can start to predict it based on
+		 * the number of children of each event it processes and whether it
+		 * plans on visiting those children
+		 * </p>
+		 */
+		private int fPredictedWorkRemaining;
+
+		/**
+		 * {@link Map}&lt{@link IResource}, {@link ResourceEvent}&gt
+		 * <p>
+		 * Map of resources events created and batched up by this visitor.
+		 * These events are periodical be sent off to the
+		 * {@link ResourceEventProcessingJob} but need to be sent off one
+		 * final time after this visitor finishes it work.
+		 * </p>
+		 * 
+		 * @see #processBatchedResourceEvents()
+		 */
+		private Map fBatchedResourceEvents;
+
+		/**
+		 * <p>
+		 * Creates a visitor that will create resource events based on the
+		 * resources it visits and using the given source as the source of the
+		 * events.
+		 * </p>
+		 * 
+		 * @param source
+		 *            The source of the events that should be used when
+		 *            creating resource events from visited resources
+		 * 
+		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
+		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
+		 */
+		protected ResourceDeltaVisitor(byte source) {
+			this(SubMonitor.convert(null), source);
+		}
+
+		/**
+		 * <p>
+		 * Creates a visitor that will create resource events based on the
+		 * resources it visits and using the given source as the source of the
+		 * events and report its status to the given progress as best it can
+		 * as it visits resources.
+		 * </p>
+		 * 
+		 * <p>
+		 * <b>NOTE:</b> While the {@link SubMonitor} is provided to report
+		 * status the visitor will not honor any cancellation requests.
+		 * </p>
+		 * 
+		 * @param progress
+		 *            Used to report status. This visitor can <b>not</b> be
+		 *            canceled
+		 * @param source
+		 *            The source of the events that should be used when
+		 *            creating resource events from visited resources
+		 * 
+		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
+		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
+		 */
+		protected ResourceDeltaVisitor(SubMonitor progress, byte source) {
+			this.fProgress = progress;
+			this.fSource = source;
+			this.fBatchedResourceEvents = new LinkedHashMap(BATCH_UP_AMOUNT);
+			this.fPredictedWorkRemaining = 1;
+		}
+
+		/**
+		 * <p>
+		 * Transforms each {@link IResourceDelta} into a {@link ResourceEvent}
+		 * . Batches up these {@link ResourceEvent}s and then passes them onto
+		 * the {@link ResourceEventProcessingJob}.
+		 * </p>
+		 * 
+		 * <p>
+		 * <b>NOTE 1: </b> Be sure to call
+		 * {@link ResourceDeltaVisitor#processBatchedResourceEvents()} after
+		 * using this visitor to be sure any remaining events get passed onto
+		 * the {@link ResourceEventProcessingJob}.
+		 * </p>
+		 * 
+		 * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
+		 * @see #processBatchedResourceEvents()
+		 */
+		public boolean visit(IResourceDelta delta) throws CoreException {
+			// report status
+			this.fProgress.subTask(NLS.bind(SSECoreMessages.IndexManager_0_resources_to_go_1, new Object[]{"" + fPredictedWorkRemaining, delta.getFullPath().toString()})); //$NON-NLS-1$
+
+			// process delta if resource not hidden
+			boolean visitChildren = false;
+
+			/*
+			 * if root node always visit its children else ask manager
+			 * implementation if resource and its children should be visited
+			 */
+			if (delta.getResource().isDerived()) { // Do not include derived
+													// resources
+				visitChildren = false;
+			}
+			else if (delta.getFullPath().isRoot()) { //$NON-NLS-1$
+				visitChildren = true;
+			}
+			else {
+				IResource resource = delta.getResource();
+
+				// check if should index resource or its children
+				if (isResourceToIndex(resource.getType(), resource.getFullPath())) {
+					if (resource.getType() == IResource.FILE) {
+
+						switch (delta.getKind()) {
+							case IResourceDelta.CHANGED : {
+								/*
+								 * ignore any change that is not a CONTENT,
+								 * REPLACED, TYPE, or MOVE_FROM change
+								 */
+								if (!((delta.getFlags() & IResourceDelta.CONTENT) != 0) && !((delta.getFlags() & IResourceDelta.REPLACED) != 0) && !((delta.getFlags() & IResourceDelta.TYPE) != 0) && !(((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0))) {
+
+									break;
+								}
+							}
+							/*
+							 * it is intended that sometimes a change will
+							 * fall through to add
+							 */
+							//$FALL-THROUGH$
+							case IResourceDelta.ADDED : {
+								if ((delta.getFlags() & IResourceDelta.MOVED_FROM) != 0) {
+									// create add move from action
+									this.fBatchedResourceEvents.put(resource, new ResourceEvent(this.fSource, AbstractIndexManager.ACTION_ADD_MOVE_FROM, delta.getMovedFromPath()));
+
+								}
+								else {
+									// create add action
+									this.fBatchedResourceEvents.put(resource, new ResourceEvent(this.fSource, AbstractIndexManager.ACTION_ADD, null));
+								}
+
+								break;
+							}
+							case IResourceDelta.REMOVED : {
+								if ((delta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
+									// create remove move to action
+									this.fBatchedResourceEvents.put(resource, new ResourceEvent(this.fSource, AbstractIndexManager.ACTION_REMOVE_MOVE_TO, delta.getMovedToPath()));
+								}
+								else {
+									// create remove action
+									this.fBatchedResourceEvents.put(resource, new ResourceEvent(this.fSource, AbstractIndexManager.ACTION_REMOVE, null));
+								}
+								break;
+							}
+						}
+					}// end is file
+
+					visitChildren = true;
+				}
+				else {
+					visitChildren = false;
+				}
+
+
+
+				// deal with trying to report progress
+				if (visitChildren) {
+					this.fPredictedWorkRemaining += delta.getAffectedChildren().length;
+				}
+				this.fProgress.setWorkRemaining(this.fPredictedWorkRemaining);
+				this.fProgress.worked(1);
+				--this.fPredictedWorkRemaining;
+
+				// batch up resource changes before sending them out
+				if (this.fBatchedResourceEvents.size() >= BATCH_UP_AMOUNT) {
+					this.processBatchedResourceEvents();
+				}
+			}
+
+			return visitChildren;
+		}
+
+		/**
+		 * <p>
+		 * Sends any batched up resource events created by this visitor to the
+		 * {@link ResourceEventProcessingJob}.
+		 * <p>
+		 * 
+		 * <p>
+		 * <b>NOTE:</b> This will be called every so often as the visitor is
+		 * visiting resources but needs to be called a final time by the user
+		 * of this visitor to be sure the final events are sent off
+		 * </p>
+		 */
+		protected void processBatchedResourceEvents() {
+			AbstractIndexManager.this.fResourceEventProcessingJob.addResourceEvents(this.fBatchedResourceEvents);
+			this.fBatchedResourceEvents.clear();
+		}
+	}
+
+	/**
+	 * <p>
+	 * Collects {@link ResourceEvent}s from the different sources and then
+	 * processes each one by calling
+	 * {@link AbstractIndexManager#performAction(byte, byte, IResource, IPath)}
+	 * for each {@link ResourceEvent}.
+	 * </p>
+	 * 
+	 * @see AbstractIndexManager#performAction(byte, byte, IResource, IPath)
+	 */
+	private class ResourceEventProcessingJob extends Job {
+		/** Length to delay when scheduling job */
+		private static final int DELAY = 500;
+
+		/**
+		 * <p>
+		 * Name of the file where resource events still to index will be
+		 * preserved for the next start up.
+		 * </p>
+		 */
+		private static final String PRESERVED_RESOURCE_EVENTS_TO_PROCESS_FILE_NAME = ".preservedResourceEvents"; //$NON-NLS-1$
+
+		/**
+		 * <p>
+		 * This needs to be updated if
+		 * {@link #preserveReceivedResourceEvents()} ever changes how it
+		 * persists resource events so that
+		 * {@link #loadPreservedReceivedResourceEvents(SubMonitor)} knows when
+		 * opening a file that the format is of the current version and if not
+		 * knows it does not know how to read the older version.
+		 * </p>
+		 * 
+		 * @see #preserveReceivedResourceEvents()
+		 * @see #loadPreservedReceivedResourceEvents(SubMonitor)
+		 */
+		private static final long serialVersionUID = 1L;
+
+		/** Whether this job has been paused or not */
+		private volatile boolean fIsPaused;
+
+		/**
+		 * {@link Map}&lt{@link IResource}, {@link ResourceEvent}&gt
+		 * <p>
+		 * The list of resources events to be processed
+		 * </p>
+		 */
+		private Map fResourceEvents;
+
+		/** Lock used when accessing {@link #fBatchedResourceEvents} */
+		private final Object fResourceEventsLock = new Object();
+
+		/**
+		 * Locked used for allowing other jobs to wait on this job. This job
+		 * will notify those waiting on this lock whenever it is done
+		 * processing all resource events it currently knows about.
+		 * 
+		 * @see #waitForConsistant(int)
+		 */
+		private final Object fToNotifyLock = new Object();
+
+		/**
+		 * <p>
+		 * Sets up this job as a long running system job
+		 * </p>
+		 */
+		protected ResourceEventProcessingJob() {
+			super(NLS.bind(SSECoreMessages.IndexManager_0_Processing_resource_events, AbstractIndexManager.this.fName));
+
+			// set this up as a long running system job
+			this.setUser(false);
+			this.setSystem(true);
+			this.setPriority(Job.LONG);
+
+			this.fIsPaused = false;
+			this.fResourceEvents = new LinkedHashMap();
+		}
+
+		/**
+		 * <p>
+		 * Loads any preserved {@link ResourceEvent}s from the last time
+		 * {@link #stop(boolean)} was invoked and schedules the job to be run
+		 * </p>
+		 * 
+		 * <p>
+		 * <b>NOTE: </b>Should be used instead of of calling
+		 * {@link Job#schedule()} because this method also takes care of
+		 * loading preserved state.
+		 * </p>
+		 * 
+		 * @param loadPreservedResourceEvents
+		 *            <code>true</code> if should load any preserved
+		 *            {@link ResourceEvent}s from the last time
+		 *            {@link #stop(boolean)} was invoked
+		 * 
+		 * @return <code>true</code> if either
+		 *         <code>loadPreservedResourceEvents</code> was false or there
+		 *         was success in loading the preserved {@link ResourceEvent}
+		 *         s. If <code>false</code> then some {@link ResourceEvent}s
+		 *         may have been loosed and to insure index consistency with
+		 *         the workspace a full workspace re-index is needed.
+		 * 
+		 * @see #stop(boolean)
+		 */
+		protected synchronized boolean start(boolean loadPreservedResourceEvents, SubMonitor progress) {
+
+			boolean successLoadingPreserved = true;
+
+			// attempt to load preserved resource events if requested
+			if (!loadPreservedResourceEvents) {
+				File preservedResourceEventsFile = this.getPreservedResourceEventsFile();
+				preservedResourceEventsFile.delete();
+			}
+			else {
+				successLoadingPreserved = this.loadPreservedReceivedResourceEvents(progress);
+			}
+
+			// start up the job
+			this.schedule();
+
+			return successLoadingPreserved;
+		}
+
+		/**
+		 * <p>
+		 * Immediately stops the job and preserves any {@link ResourceEvent}s
+		 * in the queue to be processed by not yet processed if requested
+		 * </p>
+		 * 
+		 * @param preserveResourceEvents
+		 *            <code>true</code> to preserve any {@link ResourceEvent}s
+		 *            in the queue yet to be processed, <code>false</code>
+		 *            otherwise
+		 * 
+		 * @return <code>true</code> if either
+		 *         <code>preserveResourceEvents</code> is <code>false</code>
+		 *         or if there was success in preserving the
+		 *         {@link ResourceEvent}s yet to be processed. If
+		 *         <code>false</code> then the preserving failed and a full
+		 *         workspace re-processing is needed the next time the manager
+		 *         is started
+		 * 
+		 * @throws InterruptedException
+		 *             This could happen when trying to cancel or join the job
+		 *             in progress, but it really shouldn't
+		 * 
+		 * @see #start(boolean, SubMonitor)
+		 */
+		protected synchronized boolean stop(boolean preserveResourceEvents) throws InterruptedException {
+			// this will not block indefinitely because it is known this job
+			// can be canceled
+			this.cancel();
+			this.join();
+
+			// preserve if requested, else be sure no preserve file is left
+			// over for next start
+			boolean success = true;
+			if (preserveResourceEvents && this.hasResourceEventsToProcess()) {
+				success = this.preserveReceivedResourceEvents();
+			}
+			else {
+				this.getPreservedResourceEventsFile().delete();
+			}
+
+			return success;
+		}
+
+		/**
+		 * @return <code>true</code> if job is currently running or paused
+		 * 
+		 * @see #pause()
+		 * @see #unPause()
+		 */
+		protected synchronized boolean isProcessing() {
+			return this.getState() != Job.NONE || this.fIsPaused;
+		}
+
+		/**
+		 * <p>
+		 * Un-pauses this job. This has no effect if the job is already
+		 * running.
+		 * </p>
+		 * <p>
+		 * This should be used in place of {@link Job#schedule()} to reset
+		 * state caused by calling {@link #pause()}
+		 * </p>
+		 * 
+		 * @see #pause()
+		 */
+		protected synchronized void unPause() {
+			this.fIsPaused = false;
+
+			// get the job running again depending on its current state
+			if (this.getState() == Job.SLEEPING) {
+				this.wakeUp(DELAY);
+			}
+			else {
+				this.schedule(DELAY);
+			}
+		}
+
+		/**
+		 * <p>
+		 * Pauses this job, even if it is running
+		 * </p>
+		 * <p>
+		 * This should be used in place of {@link Job#sleep()} because
+		 * {@link Job#sleep()} will not pause a job that is already running
+		 * but calling this will pause this job even if it is running.
+		 * {@link #unPause()} must be used to start this job again
+		 * </p>
+		 * 
+		 * @see #unPause()
+		 */
+		protected synchronized void pause() {
+			// if job is already running this will force it to pause
+			this.fIsPaused = true;
+
+			// this only works if the job is not running
+			this.sleep();
+		}
+
+		/**
+		 * <p>
+		 * Adds a batch of {@link ResourceEvent}s to the queue of events to be
+		 * processed. Will also un-pause the job if it is not already running
+		 * </p>
+		 * 
+		 * @param resourceEvents
+		 *            {@link Map}&lt{@link IResource}, {@link ResourceEvent}
+		 *            &gt A batch of {@link ResourceEvent}s to be processed
+		 * 
+		 * @see #addResourceEvent(ResourceEvent)
+		 * @see #unPause()
+		 */
+		protected void addResourceEvents(Map resourceEvents) {
+			Iterator iter = resourceEvents.keySet().iterator();
+			while (iter.hasNext()) {
+				IResource resource = (IResource) iter.next();
+				ResourceEvent resourceEvent = (ResourceEvent) resourceEvents.get(resource);
+				addResourceEvent(resource, resourceEvent);
+			}
+
+			// un-pause the processor if it is not already running
+			if (!isProcessing()) {
+				this.unPause();
+			}
+		}
+
+		/**
+		 * <p>
+		 * Gets the number of {@link ResourceEvent}s left to process by this
+		 * job. This count is only valid for the exact moment it is returned
+		 * because events are constantly being added and removed from the
+		 * queue of events to process
+		 * </p>
+		 * 
+		 * @return the number of {@link ResourceEvent}s left to process
+		 */
+		protected int getNumResourceEventsToProcess() {
+			return this.fResourceEvents.size();
+		}
+
+		/**
+		 * <p>
+		 * Blocks until either the given timeout elapses (0 means never to
+		 * timeout), or there are currently no {@link ResourceEvent}s to
+		 * process or being processed by this job
+		 * </p>
+		 * 
+		 * @param timeout
+		 *            block until either this timeout elapses (0 means never
+		 *            to timeout) or there are currently no
+		 *            {@link ResourceEvent}s to process or being processed by
+		 *            this job
+		 * 
+		 * @throws InterruptedException
+		 *             This can happen when waiting for a lock
+		 */
+		protected void waitForConsistant(int timeout) throws InterruptedException {
+			if (hasResourceEventsToProcess() || isProcessing()) {
+				synchronized (this.fToNotifyLock) {
+					this.fToNotifyLock.wait(timeout);
+				}
+			}
+		}
+
+		/**
+		 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+		 */
+		protected IStatus run(IProgressMonitor monitor) {
+			try {
+				// report status
+				SubMonitor progress = SubMonitor.convert(monitor);
+
+				while (!this.fIsPaused && !monitor.isCanceled() && this.hasResourceEventsToProcess()) {
+					// report status
+					progress.setTaskName(NLS.bind(SSECoreMessages.IndexManager_0_Indexing_1_Files, new Object[]{AbstractIndexManager.this.fName, "" + getNumResourceEventsToProcess()})); //$NON-NLS-1$
+					progress.setWorkRemaining(getNumResourceEventsToProcess());
+
+					// get the next event to process
+					ResourceEvent resourceEvent = null;
+					IResource resource = null;
+					synchronized (this.fResourceEventsLock) {
+						resource = (IResource) this.fResourceEvents.keySet().iterator().next();
+						resourceEvent = (ResourceEvent) this.fResourceEvents.remove(resource);
+					}
+
+					// report status
+					monitor.subTask(resource.getName());
+
+					// perform action safely
+					final byte source = resourceEvent.fSource;
+					final byte action = resourceEvent.fAction;
+					final IResource finResource = resource;
+					final IPath movePath = resourceEvent.fMovePath;
+					SafeRunner.run(new ISafeRunnable() {
+						public void run() throws Exception {
+							AbstractIndexManager.this.performAction(source, action, finResource, movePath);
+						}
+
+						public void handleException(Throwable e) {
+							Logger.logException("Error while performing an update to the index. " + //$NON-NLS-1$
+										AbstractIndexManager.LOG_ERROR_INDEX_INVALID, e);
+						}
+					});
+
+					// report progress
+					progress.worked(1);
+
+					// avoid dead locks
+					Job.getJobManager().currentJob().yieldRule(monitor);
+				}
+
+				// done work
+				monitor.done();
+			}
+			finally {
+				// want to be sure we notify no matter how we exit
+				this.notifyIfConsistant();
+			}
+
+			/*
+			 * if canceled then return CANCEL, else if done or paused return
+			 * OK
+			 */
+			IStatus exitStatus;
+			if (monitor.isCanceled()) {
+				exitStatus = Status.CANCEL_STATUS;
+			}
+			else {
+				exitStatus = Status.OK_STATUS;
+			}
+
+			return exitStatus;
+		}
+
+		/**
+		 * <p>
+		 * If resource not already scheduled to be processed, schedule it else
+		 * if resource already scheduled to be processed, update the action
+		 * only if the new action comes from a resource change event.
+		 * </p>
+		 * 
+		 * <p>
+		 * Ignore other sources for updating existing resource events because
+		 * all other sources are "start-up" type sources and thus only
+		 * {@link ResourceEvent} with a source of a resource change event
+		 * trump existing events.
+		 * </p>
+		 * 
+		 * @param resourceEvent
+		 *            {@link ResourceEvent} to be processed by this job
+		 */
+		private void addResourceEvent(IResource resource, ResourceEvent resourceEvent) {
+
+			synchronized (this.fResourceEventsLock) {
+				/*
+				 * if resource not already scheduled to be processed, schedule
+				 * it else if resource already scheduled to be processed,
+				 * update the action only if the new action comes from a
+				 * resource change event
+				 */
+				if (!this.fResourceEvents.containsKey(resource)) {
+					this.fResourceEvents.put(resource, resourceEvent);
+				}
+				else if (resourceEvent.fSource == AbstractIndexManager.SOURCE_RESOURCE_CHANGE) {
+					((ResourceEvent) this.fResourceEvents.get(resource)).fAction = resourceEvent.fAction;
+				}
+				else {
+					// Purposely ignoring all other resource events
+				}
+			}
+		}
+
+		/**
+		 * @return <code>true</code> if there are any resources to process,
+		 *         <code>false</code> otherwise
+		 */
+		private boolean hasResourceEventsToProcess() {
+			return !this.fResourceEvents.isEmpty();
+		}
+
+		/**
+		 * <p>
+		 * Preserves all of the resource events that have been received by
+		 * this manager but not yet processed
+		 * </p>
+		 * 
+		 * <p>
+		 * If this operation was successful then the next time the manager
+		 * starts it can load these events and process them. If it was not
+		 * successful then a full re-processing of the entire workspace will
+		 * need to take place to be sure the index is consistent.
+		 * </p>
+		 * 
+		 * <p>
+		 * <b>NOTE:</b> If this method changes how it preserves these events
+		 * then {@link #serialVersionUID} will need to be incremented so that
+		 * the manager does not attempt to load an old version of the file
+		 * that may exist in a users workspace. Also
+		 * {@link #loadPreservedReceivedResourceEvents(SubMonitor)} will have
+		 * to be updated to load the new file structure.
+		 * </p>
+		 * 
+		 * @return <code>true</code> if successfully preserved the resource
+		 *         events that have been received by not yet processed,
+		 *         <code>false</code> otherwise
+		 * 
+		 * @see #serialVersionUID
+		 * @see #loadPreservedReceivedResourceEvents(SubMonitor)
+		 */
+		private boolean preserveReceivedResourceEvents() {
+			File preservedResourceEventsFile = this.getPreservedResourceEventsFile();
+			boolean success = true;
+
+			synchronized (this.fResourceEventsLock) {
+				DataOutputStream dos = null;
+				try {
+					// if file already exists delete it
+					if (preservedResourceEventsFile.exists()) {
+						preservedResourceEventsFile.delete();
+						preservedResourceEventsFile.createNewFile();
+					}
+
+					// create output objects
+					FileOutputStream fos = new FileOutputStream(preservedResourceEventsFile);
+					BufferedOutputStream bos = new BufferedOutputStream(fos);
+					dos = new DataOutputStream(bos);
+
+					// write serial version
+					dos.writeLong(serialVersionUID);
+
+					// write size
+					dos.writeInt(this.getNumResourceEventsToProcess());
+
+					// write out all the information needed to restore the
+					// resource events to process
+					Iterator iter = this.fResourceEvents.keySet().iterator();
+					while (iter.hasNext()) {
+						IResource resource = (IResource) iter.next();
+						ResourceEvent resourceEvent = (ResourceEvent) this.fResourceEvents.get(resource);
+
+						if (resourceEvent.fSource != AbstractIndexManager.SOURCE_WORKSPACE_SCAN) {
+							// write out information
+							dos.writeByte(resourceEvent.fAction);
+							dos.writeByte(resource.getType());
+							byte[] pathBytes = resource.getFullPath().toString().getBytes(ENCODING_UTF16);
+							dos.write(pathBytes);
+							dos.writeByte('\0');
+							if (resourceEvent.fMovePath != null) {
+								dos.writeBytes(resourceEvent.fMovePath.toPortableString());
+							}
+							dos.writeByte('\0');
+						}
+					}
+
+					this.fResourceEvents.clear();
+
+					dos.flush();
+				}
+				catch (FileNotFoundException e) {
+					Logger.logException(AbstractIndexManager.this.fName + ": Exception while opening file to preserve resources to index.", //$NON-NLS-1$
+								e);
+					success = false;
+				}
+				catch (IOException e) {
+					Logger.logException(AbstractIndexManager.this.fName + ": Exception while writing to file to preserve resources to index.", //$NON-NLS-1$
+								e);
+					success = false;
+				}
+				finally {
+					// be sure to close output
+					if (dos != null) {
+						try {
+							dos.close();
+						}
+						catch (IOException e) {
+							Logger.logException(AbstractIndexManager.this.fName + ": Exception while closing file with preserved resources to index.", //$NON-NLS-1$
+										e);
+							success = false;
+						}
+					}
+				}
+
+				// if failed, for consistency must do a full re-process next
+				// workspace load
+				if (!success) {
+					preservedResourceEventsFile.delete();
+				}
+			}
+
+			return success;
+		}
+
+		/**
+		 * <p>
+		 * Loads the received resource events that were preserved during the
+		 * manager's last shut down so they can be processed now
+		 * </p>
+		 * 
+		 * <p>
+		 * If this operation is not successful then a full re-processing of
+		 * the entire workspace is needed to be sure the index is consistent.
+		 * </p>
+		 * 
+		 * @param progress
+		 *            used to report status of loading the preserved received
+		 *            resource events
+		 * @return <code>true</code> if the loading of the preserved received
+		 *         resource events was successful, <code>false</code>
+		 *         otherwise.
+		 * 
+		 * @see #serialVersionUID
+		 * @see #preserveReceivedResourceEvents()
+		 */
+		private boolean loadPreservedReceivedResourceEvents(SubMonitor progress) {
+			progress.subTask(SSECoreMessages.IndexManager_processing_deferred_resource_changes);
+
+			boolean success = true;
+			File preservedResourceEventsFile = this.getPreservedResourceEventsFile();
+
+			if (preservedResourceEventsFile.exists()) {
+				Map preservedResourceEvents = null;
+
+				DataInputStream dis = null;
+				try {
+					FileInputStream fis = new FileInputStream(preservedResourceEventsFile);
+					BufferedInputStream bis = new BufferedInputStream(fis);
+					dis = new DataInputStream(bis);
+
+					// check serial version first
+					long preservedSerialVersionUID = dis.readLong();
+					if (preservedSerialVersionUID == serialVersionUID) {
+
+						// read each record
+						int numberOfRecords = dis.readInt();
+						preservedResourceEvents = new LinkedHashMap(numberOfRecords);
+						progress.setWorkRemaining(numberOfRecords);
+						for (int i = 0; i < numberOfRecords; ++i) {
+							// action is first byte
+							byte action = dis.readByte();
+
+							// file type is the next byte
+							byte fileType = dis.readByte();
+
+							// resource location are the next bytes
+							ByteArrayOutputStream resourceLocationStream = new ByteArrayOutputStream();
+							byte b = dis.readByte();
+							while (b != '\0') {
+								resourceLocationStream.write(b);
+								b = dis.readByte();
+							}
+
+							// move path are the next bytes
+							ByteArrayOutputStream movePathBOS = new ByteArrayOutputStream();
+							b = dis.readByte();
+							while (b != '\0') {
+								movePathBOS.write(b);
+								b = dis.readByte();
+							}
+
+							// get the resource
+							IResource resource = null;
+							IPath resourcePath = new Path(new String(resourceLocationStream.toByteArray(), ENCODING_UTF16));
+							if (!resourcePath.isRoot() && resourcePath.segmentCount() > 1) {
+								if (fileType == IResource.FILE) {
+									resource = ResourcesPlugin.getWorkspace().getRoot().getFile(resourcePath);
+								}
+								else {
+									resource = ResourcesPlugin.getWorkspace().getRoot().getFolder(resourcePath);
+								}
+							}
+							else {
+								Logger.log(Logger.WARNING, "The AbstractIndexManager " + AbstractIndexManager.this.fName + " attempted to load an invlaid preserved resource event:\n" + "(" + resourcePath + ")");
+							}
+
+							// get the move path
+							IPath movePath = null;
+							if (movePathBOS.size() != 0) {
+								movePath = new Path(new String(movePathBOS.toByteArray(), ENCODING_UTF16));
+							}
+
+							// add the object to the list of of preserved
+							// resources
+							preservedResourceEvents.put(resource, new ResourceEvent(AbstractIndexManager.SOURCE_PRESERVED_RESOURCES_TO_INDEX, action, movePath));
+
+							progress.worked(1);
+						}
+					}
+					else {
+						success = false;
+					}
+				}
+				catch (FileNotFoundException e) {
+					Logger.logException(AbstractIndexManager.this.fName + ": Exception while opening file to read preserved resources to index. Index manager will recover by re-indexing workspace.", //$NON-NLS-1$
+								e);
+					success = false;
+				}
+				catch (IOException e) {
+					Logger.logException(AbstractIndexManager.this.fName + ": Exception while reading from file of preserved resources to index. Index manager will recover by re-indexing workspace.", //$NON-NLS-1$
+								e);
+					success = false;
+				}
+				catch (Exception e) {
+					// Purposely catching all exceptions here so that index
+					// manager can recover gracefully
+					Logger.logException(AbstractIndexManager.this.fName + ": Unexpected exception while reading from file of preserved resources to index. Index manager will recover by re-indexing workspace.", //$NON-NLS-1$
+								e);
+					success = false;
+				}
+				finally {
+					if (dis != null) {
+						try {
+							dis.close();
+						}
+						catch (IOException e) {
+							Logger.logException(AbstractIndexManager.this.fName + ": Exception while closing file of preserved resources" + //$NON-NLS-1$
+										" to index that was just read.  This should have no" + //$NON-NLS-1$
+										" effect on the consistency of the index.", //$NON-NLS-1$
+										e);
+						}
+					}
+				}
+
+				// if success loading preserved then add to master list
+				if (success && preservedResourceEvents != null) {
+					synchronized (this.fResourceEventsLock) {
+						Iterator iter = preservedResourceEvents.keySet().iterator();
+						while (iter.hasNext()) {
+							IResource resource = (IResource) iter.next();
+							ResourceEvent event = (ResourceEvent) preservedResourceEvents.get(resource);
+							this.fResourceEvents.put(resource, event);
+						}
+					}
+				}
+				else {
+					// failed reading file, so delete it
+					preservedResourceEventsFile.delete();
+				}
+			}
+
+			progress.done();
+			return success;
+		}
+
+		/**
+		 * @return {@link File} that contains any resource events received but
+		 *         not processed by this manager the last time it shutdown.
+		 *         This file may or may not actually exist.
+		 * 
+		 * @see #preserveReceivedResourceEvents()
+		 * @see #loadPreservedReceivedResourceEvents(SubMonitor)
+		 */
+		private File getPreservedResourceEventsFile() {
+			IPath preservedResourcesToIndexPath = AbstractIndexManager.this.getWorkingLocation().append(PRESERVED_RESOURCE_EVENTS_TO_PROCESS_FILE_NAME);
+			return new File(preservedResourcesToIndexPath.toOSString());
+		}
+
+		/**
+		 * <p>
+		 * If all resource events have been processed
+		 */
+		private void notifyIfConsistant() {
+			if (!this.hasResourceEventsToProcess()) {
+				synchronized (this.fToNotifyLock) {
+					this.fToNotifyLock.notifyAll();
+				}
+			}
+		}
+	}
+
+	/**
+	 * <p>
+	 * Represents a resource that was discovered by this manager. Contains all
+	 * the information this manager and the index needs to know about this
+	 * resource. Such has how the manager was notified about this resource and
+	 * the type of action occurring on the resource.
+	 * </p>
+	 */
+	private static class ResourceEvent {
+		/**
+		 * <p>
+		 * The source of this resource event
+		 * </p>
+		 * 
+		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
+		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
+		 * @see AbstractIndexManager#SOURCE_WORKSPACE_SCAN
+		 * @see AbstractIndexManager#SOURCE_PRESERVED_RESOURCES_TO_INDEX
+		 */
+		protected byte fSource;
+
+		/**
+		 * <p>
+		 * The action that the index should take with this resource
+		 * </p>
+		 * 
+		 * @see AbstractIndexManager#ACTION_ADD
+		 * @see AbstractIndexManager#ACTION_REMOVE
+		 * @see AbstractIndexManager#ACTION_ADD_MOVE_FROM
+		 * @see AbstractIndexManager#ACTION_REMOVE_MOVE_TO
+		 */
+		protected byte fAction;
+
+		/**
+		 * 
+		 * <p>
+		 * If the {@link #fAction} is
+		 * {@link AbstractIndexManager#ACTION_ADD_MOVE_FROM} or
+		 * {@link AbstractIndexManager#ACTION_REMOVE_MOVE_TO} then this field
+		 * will have the path the resource was moved from or moved to. Else
+		 * this field will be <code>null</code>
+		 * </p>
+		 * 
+		 * <p>
+		 * <b>NOTE: </b>Maybe <code>null</code>.
+		 * </p>
+		 * 
+		 * @see AbstractIndexManager#ACTION_ADD_MOVE_FROM
+		 * @see AbstractIndexManager#ACTION_REMOVE_MOVE_TO
+		 */
+		protected IPath fMovePath;
+
+		/**
+		 * <p>
+		 * Creates a resource event that the index needs to react to in some
+		 * way
+		 * </p>
+		 * 
+		 * @param source
+		 *            source that the manager used to learn of this resource
+		 * @param action
+		 *            action the index should take on this resource
+		 * @param resource
+		 *            resource that the index should know about
+		 * @param movePath
+		 *            if action is
+		 *            {@link AbstractIndexManager#ACTION_ADD_MOVE_FROM} or
+		 *            {@link AbstractIndexManager#ACTION_REMOVE_MOVE_TO} then
+		 *            this should be the path the resource was moved from or
+		 *            moved to respectively, else should be <code>null</code>
+		 * 
+		 * @see AbstractIndexManager#SOURCE_RESOURCE_CHANGE
+		 * @see AbstractIndexManager#SOURCE_SAVED_STATE
+		 * @see AbstractIndexManager#SOURCE_WORKSPACE_SCAN
+		 * @see AbstractIndexManager#SOURCE_PRESERVED_RESOURCES_TO_INDEX
+		 * 
+		 * @see AbstractIndexManager#ACTION_ADD
+		 * @see AbstractIndexManager#ACTION_REMOVE
+		 * @see AbstractIndexManager#ACTION_ADD_MOVE_FROM
+		 * @see AbstractIndexManager#ACTION_REMOVE_MOVE_TO
+		 */
+		protected ResourceEvent(byte source, byte action, IPath movePath) {
+			this.fSource = source;
+			this.fAction = action;
+			this.fMovePath = movePath;
+		}
+	}
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/FileBufferModelManager.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/FileBufferModelManager.java
new file mode 100644
index 0000000..6ae82d5
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/FileBufferModelManager.java
@@ -0,0 +1,838 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (Intalio) - bug 300434 - Make inner classes static where possible
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.filebuffers.IFileBuffer;
+import org.eclipse.core.filebuffers.IFileBufferListener;
+import org.eclipse.core.filebuffers.ITextFileBuffer;
+import org.eclipse.core.filebuffers.ITextFileBufferManager;
+import org.eclipse.core.filebuffers.LocationKind;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.content.IContentTypeManager;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.sse.core.internal.model.AbstractStructuredModel;
+import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceInUse;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.util.URIResolver;
+
+/**
+ * Not intended to be subclassed, referenced or instantiated by clients.
+ * 
+ * This class is responsible for coordinating the creation and disposal of
+ * structured models built on structured documents found in FileBuffers. It
+ * allows the SSE Model Manager to act as a client to the
+ * TextFileBufferManager.
+ */
+public class FileBufferModelManager {
+
+	static class DocumentInfo {
+		/**
+		 * The ITextFileBuffer
+		 */
+		ITextFileBuffer buffer = null;
+
+		/**
+		 * The platform content-type ID of this document
+		 */
+		String contentTypeID = null;
+
+		/**
+		 * The IStructureModel containing this document; might be null at
+		 * points in the ITextFileBuffer's lifecycle
+		 */
+		IStructuredModel model = null;
+
+		/**
+		 * Whether FileBufferModelManager called connect() for this
+		 * DocumentInfo's text filebuffer
+		 */
+		boolean selfConnected = false;
+
+		int bufferReferenceCount = 0;
+		int modelReferenceCount = 0;
+
+		/**
+		 * The default value is the "compatibility" kind from before there was
+		 * a LocationKind hint object--this is expected to be overridden at
+		 * runtime.
+		 */
+		LocationKind locationKind = LocationKind.NORMALIZE;
+	}
+
+	/**
+	 * A URIResolver instance of models built on java.io.Files
+	 */
+	static class ExternalURIResolver implements URIResolver {
+		IPath fLocation;
+
+		ExternalURIResolver(IPath location) {
+			fLocation = location;
+		}
+
+		public String getFileBaseLocation() {
+			if (fLocation == null)
+				return null;
+			else
+				return fLocation.toString();
+		}
+
+		public String getLocationByURI(String uri) {
+			return getLocationByURI(uri, getFileBaseLocation(), false);
+		}
+
+		public String getLocationByURI(String uri, boolean resolveCrossProjectLinks) {
+			return getLocationByURI(uri, getFileBaseLocation(), resolveCrossProjectLinks);
+		}
+
+		public String getLocationByURI(String uri, String baseReference) {
+			return getLocationByURI(uri, baseReference, false);
+		}
+
+		public String getLocationByURI(String uri, String baseReference, boolean resolveCrossProjectLinks) {
+			// ignore resolveCrossProjectLinks value
+			if (uri == null)
+				return null;
+			if (uri.startsWith("file:")) { //$NON-NLS-1$
+				try {
+					URL url = new URL(uri);
+					return url.getFile();
+				}
+				catch (MalformedURLException e) {
+				}
+			}
+			return URIHelper.normalize(uri, baseReference, Path.ROOT.toString());
+		}
+
+		public IProject getProject() {
+			return null;
+		}
+
+		public IContainer getRootLocation() {
+			return ResourcesPlugin.getWorkspace().getRoot();
+		}
+
+		public InputStream getURIStream(String uri) {
+			return null;
+		}
+
+		public void setFileBaseLocation(String newLocation) {
+			if (newLocation != null)
+				fLocation = new Path(newLocation);
+			else
+				fLocation = null;
+		}
+
+		public void setProject(IProject newProject) {
+		}
+	}
+
+	/**
+	 * A URIResolver instance of models built on the extensible WST URI
+	 * resolver
+	 */
+	static class CommonURIResolver implements URIResolver {
+		String fLocation;
+		IPath fPath;
+		private IProject fProject;
+		final static String SEPARATOR = "/"; //$NON-NLS-1$ 
+		final static String FILE_PREFIX = "file://"; //$NON-NLS-1$
+
+		CommonURIResolver(IFile workspaceFile) {
+			fPath = workspaceFile.getFullPath();
+			fProject = workspaceFile.getProject();
+		}
+
+		public String getFileBaseLocation() {
+			return fLocation;
+		}
+
+		public String getLocationByURI(String uri) {
+			return getLocationByURI(uri, getFileBaseLocation(), false);
+		}
+
+		public String getLocationByURI(String uri, boolean resolveCrossProjectLinks) {
+			return getLocationByURI(uri, getFileBaseLocation(), resolveCrossProjectLinks);
+		}
+
+		public String getLocationByURI(String uri, String baseReference) {
+			return getLocationByURI(uri, baseReference, false);
+		}
+
+		public String getLocationByURI(String uri, String baseReference, boolean resolveCrossProjectLinks) {
+			boolean baseHasPrefix = baseReference != null && baseReference.startsWith(FILE_PREFIX);
+			String reference = null;
+			if (baseHasPrefix) {
+				reference = baseReference;
+			}
+			else {
+				reference = FILE_PREFIX + baseReference;
+			}
+			String result = URIResolverPlugin.createResolver().resolve(reference, null, uri);
+			// Logger.log(Logger.INFO_DEBUG,
+			// "URIResolverPlugin.createResolver().resolve("
+			// + reference + ", null, " +uri+") = " + result);
+			if (!baseHasPrefix && result.startsWith(FILE_PREFIX) && result.length() > FILE_PREFIX.length()) {
+				result = result.substring(FILE_PREFIX.length());
+			}
+			return result;
+		}
+
+		public IProject getProject() {
+			return fProject;
+		}
+
+		public IContainer getRootLocation() {
+			String root = URIResolverPlugin.createResolver().resolve(FILE_PREFIX + getFileBaseLocation(), null, SEPARATOR);
+			IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(new Path(root));
+			for (int i = 0; i < files.length; i++) {
+				if ((files[i].getType() & IResource.FOLDER) == IResource.FOLDER) {
+					if (fPath.isPrefixOf(((IFolder) files[i]).getFullPath())) {
+						return (IFolder) files[i];
+					}
+				}
+			}
+			return getProject();
+		}
+
+		public InputStream getURIStream(String uri) {
+			return null;
+		}
+
+		public void setFileBaseLocation(String newLocation) {
+			fLocation = newLocation;
+		}
+
+		public void setProject(IProject newProject) {
+			fProject = newProject;
+		}
+	}
+
+	/**
+	 * Maps interesting documents in file buffers to those file buffers.
+	 * Required to allow us to go from the document instances to complete
+	 * models.
+	 */
+	class FileBufferMapper implements IFileBufferListener {
+		public void bufferContentAboutToBeReplaced(IFileBuffer buffer) {
+		}
+
+		public void bufferContentReplaced(IFileBuffer buffer) {
+		}
+
+		public void bufferCreated(IFileBuffer buffer) {
+			if (buffer instanceof ITextFileBuffer) {
+				ITextFileBuffer textBuffer = (ITextFileBuffer) buffer;
+				if (!(textBuffer.getDocument() instanceof IStructuredDocument))
+					return;
+
+				if (Logger.DEBUG_TEXTBUFFERLIFECYCLE) {
+					Logger.log(Logger.INFO, "Learned new buffer: " + buffer.getLocation().toString() + " " + buffer + " " + ((ITextFileBuffer) buffer).getDocument()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				}
+				DocumentInfo info = new DocumentInfo();
+				info.buffer = textBuffer;
+				info.contentTypeID = detectContentType(buffer.getLocation()).getId();
+				info.bufferReferenceCount++;
+				fDocumentMap.put(textBuffer.getDocument(), info);
+			}
+		}
+
+		public void bufferDisposed(IFileBuffer buffer) {
+			if (buffer instanceof ITextFileBuffer) {
+				ITextFileBuffer textBuffer = (ITextFileBuffer) buffer;
+				if (!(textBuffer.getDocument() instanceof IStructuredDocument))
+					return;
+				if (Logger.DEBUG_TEXTBUFFERLIFECYCLE) {
+					Logger.log(Logger.INFO, "Discarded buffer: " + buffer.getLocation().toString() + " " + buffer + " " + ((ITextFileBuffer) buffer).getDocument()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				}
+				DocumentInfo info = (DocumentInfo) fDocumentMap.get(textBuffer.getDocument());
+				if (info != null) {
+					info.bufferReferenceCount--;
+					checkReferenceCounts(info, textBuffer.getDocument());
+				}
+			}
+		}
+
+		public void dirtyStateChanged(IFileBuffer buffer, boolean isDirty) {
+			if (buffer instanceof ITextFileBuffer) {
+				if (Logger.DEBUG_TEXTBUFFERLIFECYCLE) {
+					Logger.log(Logger.INFO, "Buffer dirty state changed: (" + isDirty + ") " + buffer.getLocation().toString() + " " + buffer + " " + ((ITextFileBuffer) buffer).getDocument()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+				}
+				ITextFileBuffer textBuffer = (ITextFileBuffer) buffer;
+				if (!(textBuffer.getDocument() instanceof IStructuredDocument))
+					return;
+				DocumentInfo info = (DocumentInfo) fDocumentMap.get(textBuffer.getDocument());
+				if (info != null && info.model != null) {
+					String msg = "Updating model dirty state for" + info.buffer.getLocation(); //$NON-NLS-1$
+					if (Logger.DEBUG_FILEBUFFERMODELMANAGEMENT || Logger.DEBUG_TEXTBUFFERLIFECYCLE) {
+						Logger.log(Logger.INFO, msg);
+					}
+					info.model.setDirtyState(isDirty);
+
+					IFile workspaceFile = FileBuffers.getWorkspaceFileAtLocation(info.buffer.getLocation());
+					if (!isDirty && workspaceFile != null) {
+						info.model.resetSynchronizationStamp(workspaceFile);
+					}
+				}
+			}
+		}
+
+		public void stateChangeFailed(IFileBuffer buffer) {
+		}
+
+		public void stateChanging(IFileBuffer buffer) {
+		}
+
+		public void stateValidationChanged(IFileBuffer buffer, boolean isStateValidated) {
+		}
+
+		public void underlyingFileDeleted(IFileBuffer buffer) {
+			if (buffer instanceof ITextFileBuffer) {
+				if (Logger.DEBUG_TEXTBUFFERLIFECYCLE) {
+					Logger.log(Logger.INFO, "Deleted buffer: " + buffer.getLocation().toOSString() + " " + buffer); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+		}
+
+		public void underlyingFileMoved(IFileBuffer buffer, IPath path) {
+			if (buffer instanceof ITextFileBuffer) {
+				if (Logger.DEBUG_TEXTBUFFERLIFECYCLE) {
+					Logger.log(Logger.INFO, "Moved buffer from: " + buffer.getLocation().toOSString() + " " + buffer); //$NON-NLS-1$ //$NON-NLS-2$
+					Logger.log(Logger.INFO, "Moved buffer to: " + path.toOSString() + " " + buffer); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+		}
+	}
+
+	private static FileBufferModelManager instance = new FileBufferModelManager();
+
+	public static FileBufferModelManager getInstance() {
+		return instance;
+	}
+
+	static synchronized final void shutdown() {
+		FileBuffers.getTextFileBufferManager().removeFileBufferListener(instance.fFileBufferListener);
+
+		if (Logger.DEBUG_FILEBUFFERMODELMANAGEMENT || Logger.DEBUG_FILEBUFFERMODELLEAKS) {
+			IDocument[] danglingDocuments = (IDocument[]) instance.fDocumentMap.keySet().toArray(new IDocument[0]);
+			for (int i = 0; i < danglingDocuments.length; i++) {
+				DocumentInfo info = (DocumentInfo) instance.fDocumentMap.get(danglingDocuments[i]);
+				if (info.modelReferenceCount > 0)
+					System.err.println("LEAKED MODEL: " + info.buffer.getLocation() + " " + (info.model != null ? info.model.getId() : null)); //$NON-NLS-1$ //$NON-NLS-2$
+				if (info.bufferReferenceCount > 0)
+					System.err.println("LEAKED BUFFER: " + info.buffer.getLocation() + " " + info.buffer.getDocument()); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+		}
+	}
+
+	static synchronized final void startup() {
+		FileBuffers.getTextFileBufferManager().addFileBufferListener(getInstance().fFileBufferListener);
+	}
+
+	// a map of IStructuredDocuments to DocumentInfo objects
+	Map fDocumentMap = null;
+
+	FileBufferMapper fFileBufferListener = new FileBufferMapper();
+
+	FileBufferModelManager() {
+		super();
+		fDocumentMap = new Hashtable(4);
+	}
+
+	public String calculateId(IFile file) {
+		if (file == null) {
+			Exception iae = new IllegalArgumentException("can not calculate a model ID without an IFile"); //$NON-NLS-1$ 
+			Logger.logException(iae);
+			return null;
+		}
+
+		String id = null;
+		IPath path = file.getFullPath();
+		if (path != null) {
+			/*
+			 * The ID of models must be the same as the normalized paths
+			 * stored in the underlying FileBuffers to retrieve them by common
+			 * ID later on. We chose the FileBuffer normalized path over the
+			 * previously used absolute IFile path because the buffers should
+			 * already exist before we build a model and we can't retrieve a
+			 * FileBuffer using the ID of a model that doesn't yet exist.
+			 */
+			id = FileBuffers.normalizeLocation(path).toString();
+		}
+		return id;
+
+	}
+
+
+	public String calculateId(IDocument document) {
+		if (document == null) {
+			Exception iae = new IllegalArgumentException("can not calculate a model ID without a document reference"); //$NON-NLS-1$ 
+			Logger.logException(iae);
+			return null;
+		}
+
+		String id = null;
+		ITextFileBuffer buffer = getBuffer(document);
+		if (buffer != null) {
+			id = buffer.getLocation().toString();
+		}
+		return id;
+	}
+
+	/**
+	 * Registers "interest" in a document, or rather the file buffer that
+	 * backs it. Intentionally used to alter the reference count of the file
+	 * buffer so it is not accidentally disposed of while we have a model open
+	 * on top of it.
+	 */
+	public boolean connect(IDocument document) {
+		if (document == null) {
+			Exception iae = new IllegalArgumentException("can not connect() without a document"); //$NON-NLS-1$ 
+			Logger.logException(iae);
+			return false;
+		}
+		DocumentInfo info = (DocumentInfo) fDocumentMap.get(document);
+		if (info == null)
+			return false;
+		ITextFileBufferManager bufferManager = FileBuffers.getTextFileBufferManager();
+		IPath bufferLocation = info.buffer.getLocation();
+		boolean isOK = true;
+		try {
+			bufferManager.connect(bufferLocation, info.locationKind, null);
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+			isOK = false;
+		}
+		return isOK;
+	}
+
+	URIResolver createURIResolver(ITextFileBuffer buffer) {
+		IPath location = buffer.getLocation();
+		IFile workspaceFile = FileBuffers.getWorkspaceFileAtLocation(location);
+		URIResolver resolver = null;
+		if (workspaceFile != null) {
+			IProject project = workspaceFile.getProject();
+			resolver = (URIResolver) project.getAdapter(URIResolver.class);
+			if (resolver == null) {
+				resolver = new CommonURIResolver(workspaceFile);
+			}
+			
+			String baseLocation = null;
+			if (workspaceFile.getLocation() != null) {
+				baseLocation = workspaceFile.getLocation().toString();
+			}
+			if (baseLocation == null && workspaceFile.getLocationURI() != null) {
+				baseLocation = workspaceFile.getLocationURI().toString();
+			}
+			if (baseLocation == null) {
+				baseLocation = workspaceFile.getFullPath().toString();
+			}
+			resolver.setFileBaseLocation(baseLocation);
+		}
+		else {
+			resolver = new ExternalURIResolver(location);
+		}
+		return resolver;
+	}
+
+
+	IContentType detectContentType(IPath location) {
+		IContentType type = null;
+
+		IResource resource = FileBuffers.getWorkspaceFileAtLocation(location);
+		if (resource != null) {
+			if (resource.getType() == IResource.FILE && resource.isAccessible()) {
+				IContentDescription d = null;
+				try {
+					// Optimized description lookup, might not succeed
+					d = ((IFile) resource).getContentDescription();
+					if (d != null) {
+						type = d.getContentType();
+					}
+				}
+				catch (CoreException e) {
+					// Should not be possible given the accessible and file
+					// type check above
+				}
+				if (type == null) {
+					type = Platform.getContentTypeManager().findContentTypeFor(resource.getName());
+				}
+			}
+		}
+		else {
+			File file = FileBuffers.getSystemFileAtLocation(location);
+			if (file != null) {
+				InputStream input = null;
+				try {
+					input = new FileInputStream(file);
+					type = Platform.getContentTypeManager().findContentTypeFor(input, file.getName());
+				}
+				catch (FileNotFoundException e) {
+				}
+				catch (IOException e) {
+				}
+				finally {
+					if (input != null) {
+						try {
+							input.close();
+						}
+						catch (IOException e1) {
+						}
+					}
+				}
+				if (type == null) {
+					type = Platform.getContentTypeManager().findContentTypeFor(file.getName());
+				}
+			}
+		}
+		if (type == null) {
+			type = Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT);
+		}
+		return type;
+	}
+
+	/**
+	 * Deregisters "interest" in a document, or rather the file buffer that
+	 * backs it. Intentionally used to alter the reference count of the file
+	 * buffer so that it knows it can safely be disposed of.
+	 */
+	public boolean disconnect(IDocument document) {
+		if (document == null) {
+			Exception iae = new IllegalArgumentException("can not disconnect() without a document"); //$NON-NLS-1$ 
+			Logger.logException(iae);
+			return false;
+		}
+		DocumentInfo info = (DocumentInfo) fDocumentMap.get(document);
+		if( info == null)
+			return false;
+		ITextFileBufferManager bufferManager = FileBuffers.getTextFileBufferManager();
+		IPath bufferLocation = info.buffer.getLocation();
+		boolean isOK = true;
+		try {
+			bufferManager.disconnect(bufferLocation, info.locationKind, null);
+		}
+		catch (CoreException e) {
+			Logger.logException(e);
+			isOK = false;
+		}
+		return isOK;
+	}
+
+	public ITextFileBuffer getBuffer(IDocument document) {
+		if (document == null) {
+			Exception iae = new IllegalArgumentException("can not get a buffer without a document reference"); //$NON-NLS-1$ 
+			Logger.logException(iae);
+			return null;
+		}
+
+		DocumentInfo info = (DocumentInfo) fDocumentMap.get(document);
+		if (info != null)
+			return info.buffer;
+		return null;
+	}
+
+	String getContentTypeID(IDocument document) {
+		DocumentInfo info = (DocumentInfo) fDocumentMap.get(document);
+		if (info != null)
+			return info.contentTypeID;
+		return null;
+	}
+
+	IStructuredModel getModel(File file) {
+		if (file == null) {
+			Exception iae = new IllegalArgumentException("can not get/create a model without a java.io.File"); //$NON-NLS-1$ 
+			Logger.logException(iae);
+			return null;
+		}
+
+		IStructuredModel model = null;
+		ITextFileBufferManager bufferManager = FileBuffers.getTextFileBufferManager();
+		try {
+			IPath location = new Path(file.getAbsolutePath());
+			if (Logger.DEBUG_FILEBUFFERMODELMANAGEMENT) {
+				Logger.log(Logger.INFO, "FileBufferModelManager connecting to File " + location); //$NON-NLS-1$
+			}
+			bufferManager.connect(location, LocationKind.LOCATION, getProgressMonitor());
+			ITextFileBuffer buffer = bufferManager.getTextFileBuffer(location, LocationKind.LOCATION);
+			if (buffer != null) {
+				DocumentInfo info = (DocumentInfo) fDocumentMap.get(buffer.getDocument());
+				if (info != null) {
+					/*
+					 * Note: "info" being null at this point is a slight
+					 * error.
+					 * 
+					 * The connect call from above (or at some time earlier in
+					 * the session) would have notified the FileBufferMapper
+					 * of the creation of the corresponding text buffer and
+					 * created the DocumentInfo object for
+					 * IStructuredDocuments.
+					 */
+					info.locationKind = LocationKind.LOCATION;
+					info.selfConnected = true;
+				}
+				/*
+				 * Check the document type. Although returning null for
+				 * unknown documents would be fair, try to get a model if
+				 * the document is at least a valid type.
+				 */
+				IDocument bufferDocument = buffer.getDocument();
+				if (bufferDocument instanceof IStructuredDocument) {
+					model = getModel((IStructuredDocument) bufferDocument);
+				}
+				else {
+					/*
+					 * 190768 - Quick diff marks do not disappear in the
+					 * vertical ruler of JavaScript editor and
+					 * 
+					 * 193805 - Changes are not thrown away when close
+					 * with no save for files with no structured model
+					 * associated with them (text files, javascript files,
+					 * etc) in web project
+					 */
+					bufferManager.disconnect(location, LocationKind.IFILE, getProgressMonitor());
+				}
+			}
+		}
+		catch (CoreException e) {
+			Logger.logException("Error getting model for " + file.getPath(), e); //$NON-NLS-1$
+		}
+		return model;
+	}
+
+	public IStructuredModel getModel(IFile file) {
+		if (file == null) {
+			Exception iae = new IllegalArgumentException("can not get/create a model without an IFile"); //$NON-NLS-1$ 
+			Logger.logException(iae);
+			return null;
+		}
+
+		IStructuredModel model = null;
+		ITextFileBufferManager bufferManager = FileBuffers.getTextFileBufferManager();
+		try {
+			if (Logger.DEBUG_FILEBUFFERMODELMANAGEMENT) {
+				Logger.log(Logger.INFO, "FileBufferModelManager connecting to IFile " + file.getFullPath()); //$NON-NLS-1$
+			}
+			// see TextFileDocumentProvider#createFileInfo about why we use
+			// IFile#getFullPath
+			// here, not IFile#getLocation.
+			IPath location = file.getFullPath();
+			if (location != null) {
+				bufferManager.connect(location, LocationKind.IFILE, getProgressMonitor());
+				ITextFileBuffer buffer = bufferManager.getTextFileBuffer(location, LocationKind.IFILE);
+				if (buffer != null) {
+					DocumentInfo info = (DocumentInfo) fDocumentMap.get(buffer.getDocument());
+					if (info != null) {
+						/*
+						 * Note: "info" being null at this point is a slight
+						 * error.
+						 * 
+						 * The connect call from above (or at some time
+						 * earlier in the session) would have notified the
+						 * FileBufferMapper of the creation of the
+						 * corresponding text buffer and created the
+						 * DocumentInfo object for IStructuredDocuments.
+						 */
+						info.selfConnected = true;
+						info.locationKind = LocationKind.IFILE;
+					}
+					/*
+					 * Check the document type. Although returning null for
+					 * unknown documents would be fair, try to get a model if
+					 * the document is at least a valid type.
+					 */
+					IDocument bufferDocument = buffer.getDocument();
+					if (bufferDocument instanceof IStructuredDocument) {
+						model = getModel((IStructuredDocument) bufferDocument);
+					}
+					else {
+						/*
+						 * 190768 - Quick diff marks do not disappear in the
+						 * vertical ruler of JavaScript editor and
+						 * 
+						 * 193805 - Changes are not thrown away when close
+						 * with no save for files with no structured model
+						 * associated with them (text files, javascript files,
+						 * etc) in web project
+						 */
+						bufferManager.disconnect(location, LocationKind.IFILE, getProgressMonitor());
+					}
+				}
+			}
+		}
+		catch (CoreException e) {
+			Logger.logException("Error getting model for " + file.getFullPath(), e); //$NON-NLS-1$
+		}
+		return model;
+	}
+
+	public IStructuredModel getModel(IStructuredDocument document) {
+		if (document == null) {
+			Exception iae = new IllegalArgumentException("can not get/create a model without a document reference"); //$NON-NLS-1$ 
+			Logger.logException(iae);
+			return null;
+		}
+
+		DocumentInfo info = (DocumentInfo) fDocumentMap.get(document);
+		if (info != null && info.model == null) {
+			if (Logger.DEBUG_FILEBUFFERMODELMANAGEMENT) {
+				Logger.log(Logger.INFO, "FileBufferModelManager creating model for " + info.buffer.getLocation() + " " + info.buffer.getDocument()); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			info.modelReferenceCount++;
+
+			IStructuredModel model = null;
+			IModelHandler handler = ModelHandlerRegistry.getInstance().getHandlerForContentTypeId(info.contentTypeID);
+			IModelLoader loader = handler.getModelLoader();
+			model = loader.createModel(document, info.buffer.getLocation().toString(), handler);
+			try {
+				info.model = model;
+				model.setId(info.buffer.getLocation().toString());
+				// handler now set by loader, for now
+				// model.setModelHandler(handler);
+				if (model instanceof AbstractStructuredModel) {
+					((AbstractStructuredModel) model).setContentTypeIdentifier(info.contentTypeID);
+				}
+				model.setResolver(createURIResolver(getBuffer(document)));
+				if (info.buffer.isDirty()) {
+					model.setDirtyState(true);
+				}
+			}
+			catch (ResourceInUse e) {
+				Logger.logException("attempted to create new model with existing ID", e); //$NON-NLS-1$
+				model = null;
+			}
+		}
+		if (info != null) {
+			return info.model;
+		}
+		return null;
+	}
+
+	/**
+	 * @return
+	 */
+	private IProgressMonitor getProgressMonitor() {
+		return new NullProgressMonitor();
+	}
+
+	/**
+	 * Will remove the entry corresponding to <code>document</code> if both
+	 * there are no more buffer or model reference counts for <code>info</code>
+	 * 
+	 * @param info the document info to check for reference counts
+	 * @param document the key to remove from the document map if there are no more
+	 * references
+	 */
+	private void checkReferenceCounts(DocumentInfo info, IDocument document) {
+		if (info.bufferReferenceCount == 0 && info.modelReferenceCount == 0)
+			fDocumentMap.remove(document);
+	}
+
+	public boolean isExistingBuffer(IDocument document) {
+		if (document == null) {
+			Exception iae = new IllegalArgumentException("can not check for an existing buffer without a document reference"); //$NON-NLS-1$ 
+			Logger.logException(iae);
+			return false;
+		}
+
+		DocumentInfo info = (DocumentInfo) fDocumentMap.get(document);
+		return info != null;
+	}
+
+	public void releaseModel(IDocument document) {
+		if (document == null) {
+			Exception iae = new IllegalArgumentException("can not release a model without a document reference"); //$NON-NLS-1$ 
+			Logger.logException(iae);
+			return;
+		}
+		DocumentInfo info = (DocumentInfo) fDocumentMap.get(document);
+		if (info != null) {
+			if (Logger.DEBUG_FILEBUFFERMODELMANAGEMENT) {
+				Logger.log(Logger.INFO, "FileBufferModelManager noticed full release of model for " + info.buffer.getLocation() + " " + info.buffer.getDocument()); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			info.model = null;
+			info.modelReferenceCount--;
+			if (info.selfConnected) {
+				if (Logger.DEBUG_FILEBUFFERMODELMANAGEMENT) {
+					Logger.log(Logger.INFO, "FileBufferModelManager disconnecting from " + info.buffer.getLocation() + " " + info.buffer.getDocument()); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				IPath location = info.buffer.getLocation();
+				try {
+					FileBuffers.getTextFileBufferManager().disconnect(location, info.locationKind, getProgressMonitor());
+				}
+				catch (CoreException e) {
+					Logger.logException("Error releasing model for " + location, e); //$NON-NLS-1$
+				}
+			}
+			// [265899]
+			// In some scenarios, a model can be held onto after the editor has been disposed even if the lifecycle is
+			// maintained properly (e.g., an editor being closed before a DirtyRegionProcessor has a chance to complete). Because of this,
+			// the manager cannot be reliant upon the FileBufferMapper having the sole responsibility of the fDocumentMap cleanup
+			checkReferenceCounts(info, document);
+		}
+	}
+
+	public void revert(IDocument document) {
+		if (document == null) {
+			Exception iae = new IllegalArgumentException("can not release a model without a document reference"); //$NON-NLS-1$ 
+			Logger.logException(iae);
+			return;
+		}
+		DocumentInfo info = (DocumentInfo) fDocumentMap.get(document);
+		if (info == null) {
+			Logger.log(Logger.ERROR, "FileBufferModelManager was asked to revert a document but was not being managed"); //$NON-NLS-1$
+		}
+		else {
+			// get path just for potential error message
+			IPath location = info.buffer.getLocation();
+			try {
+				// ISSUE: in future, clients should provide progress monitor
+				info.buffer.revert(getProgressMonitor());
+			}
+			catch (CoreException e) {
+				// ISSUE: shoudl we not be re-throwing CoreExceptions? Or
+				// not catch them at all?
+				Logger.logException("Error reverting model for " + location, e); //$NON-NLS-1$
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/IExecutionDelegate.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/IExecutionDelegate.java
new file mode 100644
index 0000000..63c5894
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/IExecutionDelegate.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.sse.core.internal;
+
+import org.eclipse.core.runtime.ISafeRunnable;
+
+/**
+ * An abstraction that allows even processing to be performed in a different
+ * context, e.g. a different Thread, if needed.
+ * 
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IExecutionDelegate {
+
+	void execute(ISafeRunnable runnable);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ILockable.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ILockable.java
new file mode 100644
index 0000000..c8aa500
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ILockable.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.sse.core.internal;
+
+import org.eclipse.core.runtime.jobs.ILock;
+
+/**
+ * 
+ * Not API: not to be used or implemented by clients. This is a special
+ * purpose interface to help guard some threading issues betweeen model and
+ * document. Will be changed soon.
+ *  
+ */
+
+public interface ILockable {
+
+	ILock getLockObject();
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/JSPAwareAdapterFactory.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/JSPAwareAdapterFactory.java
new file mode 100644
index 0000000..a9e2292
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/JSPAwareAdapterFactory.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal;
+
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+
+
+public interface JSPAwareAdapterFactory extends INodeAdapterFactory {
+
+	void initializeWith(EmbeddedTypeHandler embeddedContentType);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/Logger.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/Logger.java
new file mode 100644
index 0000000..f826867
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/Logger.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal;
+
+
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.Bundle;
+
+/**
+ * Small convenience class to log messages to plugin's log file and also, if
+ * desired, the console. This class should only be used by classes in this
+ * plugin. Other plugins should make their own copy, with appropriate ID.
+ */
+public class Logger {
+	private static final String PLUGIN_ID = "org.eclipse.wst.sse.core"; //$NON-NLS-1$
+	/**
+	 * true if both platform and this plugin are in debug mode
+	 */
+	public static final boolean DEBUG = Platform.inDebugMode() && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/debug")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging adapter
+	 * notification time
+	 */
+	public static final boolean DEBUG_ADAPTERNOTIFICATIONTIME = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/dom/adapter/notification/time")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging structured
+	 * document
+	 */
+	public static final boolean DEBUG_DOCUMENT = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/structureddocument")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging file buffer
+	 * model management
+	 */
+	public static final boolean DEBUG_FILEBUFFERMODELMANAGEMENT = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/filebuffers/modelmanagement")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging file buffer
+	 * models not being released on shutdown
+	 */
+	public static final boolean DEBUG_FILEBUFFERMODELLEAKS = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/filebuffers/leaks")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging formatting
+	 */
+	public static final boolean DEBUG_FORMAT = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/format")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging text buffer
+	 * lifecycle
+	 */
+	public static final boolean DEBUG_TEXTBUFFERLIFECYCLE = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/filebuffers/lifecycle")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging model
+	 * lifecycle
+	 */
+	public static final boolean DEBUG_LIFECYCLE = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/structuredmodel/lifecycle")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging model state
+	 */
+	public static final boolean DEBUG_MODELSTATE = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/structuredmodel/state")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging model lock
+	 * state
+	 */
+	public static final boolean DEBUG_MODELLOCK = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/structuredmodel/locks")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging model
+	 * manager
+	 */
+	public static final boolean DEBUG_MODELMANAGER = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/structuredmodel/modelmanager")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging task tags
+	 */
+	public static final boolean DEBUG_TASKS = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging task tags
+	 * content type detection
+	 */
+	public static final boolean DEBUG_TASKSCONTENTTYPE = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks/detection")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging task tags
+	 * jobs
+	 */
+	public static final boolean DEBUG_TASKSJOB = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks/job")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging task tags
+	 * overall performance
+	 */
+	public static final boolean DEBUG_TASKSOVERALLPERF = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks/overalltime")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging task tags
+	 * performance
+	 */
+	public static final boolean DEBUG_TASKSPERF = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks/time")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging task tags
+	 * preferences
+	 */
+	public static final boolean DEBUG_TASKSPREFS = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks/preferences")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * true if platform and plugin are in debug mode and debugging task tags
+	 * registry
+	 */
+	public static final boolean DEBUG_TASKSREGISTRY = DEBUG && "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.sse.core/tasks/registry")); //$NON-NLS-1$ //$NON-NLS-2$
+
+	/*
+	 * Keep our own copy in case we want to add other severity levels
+	 */
+	public static final int OK = IStatus.OK;
+	public static final int INFO = IStatus.INFO;
+	public static final int WARNING = IStatus.WARNING;
+	public static final int ERROR = IStatus.ERROR;
+	public static final int OK_DEBUG = 200 + OK;
+	public static final int INFO_DEBUG = 200 + INFO;
+	public static final int WARNING_DEBUG = 200 + WARNING;
+	public static final int ERROR_DEBUG = 200 + ERROR;
+
+	/**
+	 * @return true if the platform is debugging
+	 */
+	private static boolean isDebugging() {
+		return Platform.inDebugMode();
+	}
+
+	/**
+	 * Adds message to log.
+	 * 
+	 * @param level
+	 *            severity level of the message (OK, INFO, WARNING, ERROR,
+	 * @param message
+	 *            text to add to the log
+	 * @param exception
+	 *            exception thrown
+	 */
+	private static void _log(int level, String message, Throwable exception) {
+		if (level == OK_DEBUG || level == INFO_DEBUG || level == WARNING_DEBUG || level == ERROR_DEBUG) {
+			if (!isDebugging())
+				return;
+		}
+		int severity = IStatus.OK;
+		switch (level) {
+			case INFO_DEBUG :
+			case INFO :
+				severity = IStatus.INFO;
+				break;
+			case WARNING_DEBUG :
+			case WARNING :
+				severity = IStatus.WARNING;
+				break;
+			case ERROR_DEBUG :
+			case ERROR :
+				severity = IStatus.ERROR;
+		}
+		message = (message != null) ? message : ""; //$NON-NLS-1$
+		Status statusObj = new Status(severity, PLUGIN_ID, severity, message, exception);
+		Bundle bundle = Platform.getBundle(PLUGIN_ID);
+		if (bundle != null)
+			Platform.getLog(bundle).log(statusObj);
+	}
+
+	/**
+	 * Write a message to the log with the given severity level
+	 * 
+	 * @param level
+	 *            ERROR, WARNING, INFO, OK
+	 * @param message
+	 *            message to add to the log
+	 */
+	public static void log(int level, String message) {
+		_log(level, message, null);
+	}
+
+	/**
+	 * Writes a message and exception to the log with the given severity level
+	 * 
+	 * @param level
+	 *            ERROR, WARNING, INFO, OK
+	 * @param message
+	 *            message to add to the log
+	 * @param exception
+	 *            exception to add to the log
+	 */
+	public static void log(int level, String message, Throwable exception) {
+		_log(level, message, exception);
+	}
+
+	/**
+	 * Writes the exception as an error in the log along with an accompanying
+	 * message
+	 * 
+	 * @param message
+	 *            message to add to the log
+	 * @param exception
+	 *            exception to add to the log
+	 */
+	public static void logException(String message, Throwable exception) {
+		_log(IStatus.ERROR, message, exception);
+	}
+
+	/**
+	 * Writes the exception as an error in the log
+	 * 
+	 * @param exception
+	 *            exception to add to the log
+	 */
+	public static void logException(Throwable exception) {
+		_log(IStatus.ERROR, exception.getMessage(), exception);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ModelManagerPluginRegistryReader.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ModelManagerPluginRegistryReader.java
new file mode 100644
index 0000000..2b9025f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ModelManagerPluginRegistryReader.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IDocumentTypeHandler;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.osgi.framework.Bundle;
+
+
+public class ModelManagerPluginRegistryReader {
+	private static ModelManagerPluginRegistryReader reader = null;
+
+	public synchronized static ModelManagerPluginRegistryReader getInstance() {
+		if (reader == null) {
+			reader = new ModelManagerPluginRegistryReader();
+		}
+		return reader;
+	}
+
+	protected final String ATTR_ADAPTERKEY = "adapterKeyClass"; //$NON-NLS-1$
+	protected final String ATTR_CLASS = "class"; //$NON-NLS-1$
+	protected final String ATTR_CONTENTTYPE = "type"; //$NON-NLS-1$
+	protected final String ATTR_REGISTERADAPTER = "registerAdapters"; //$NON-NLS-1$
+
+	protected final String EXTENSION_POINT_ID = "adaptOnCreateFactory"; //$NON-NLS-1$
+	protected final String TAG_NAME = "AdaptOnCreateFactory"; //$NON-NLS-1$
+
+	/**
+	 * XMLEditorPluginRegistryReader constructor comment.
+	 */
+	protected ModelManagerPluginRegistryReader() {
+		super();
+	}
+
+	public List getFactories(IDocumentTypeHandler handler) {
+		return loadRegistry(handler.getId());
+	}
+
+	public List getFactories(String type) {
+		return loadRegistry(type);
+	}
+
+	protected INodeAdapterFactory loadFactoryFromConfigurationElement(IConfigurationElement element, Object requesterType) {
+		INodeAdapterFactory factory = null;
+		if (element.getName().equals(TAG_NAME)) {
+			String contentType = element.getAttribute(ATTR_CONTENTTYPE);
+			if (!contentType.equals(requesterType))
+				return null;
+			String className = element.getAttribute(ATTR_CLASS);
+			String adapterKeyClass = element.getAttribute(ATTR_ADAPTERKEY);
+			String registerAdapters = element.getAttribute(ATTR_REGISTERADAPTER);
+
+			// if className is null, then no one defined the extension point
+			// for adapter factories
+			if (className != null) {
+				String name = element.getDeclaringExtension().getNamespace();
+				Bundle bundle = null;
+				try {
+					bundle = Platform.getBundle(name);
+				}
+				catch (Exception e) {
+					// if an error occurs here, its probably that the plugin
+					// could not be found/loaded
+					Logger.logException("Could not find bundle: " + name, e); //$NON-NLS-1$
+
+				}
+				if (bundle != null) {
+					boolean useExtendedConstructor = false;
+					boolean doRegisterAdapters = false;
+					Object adapterKey = null;
+
+					if (registerAdapters != null && registerAdapters.length() > 0 && Boolean.valueOf(registerAdapters).booleanValue()) {
+						doRegisterAdapters = true;
+					}
+					if (adapterKeyClass != null) {
+						try {
+							Class aClass = null;
+							// aClass = classLoader != null ?
+							// classLoader.loadClass(adapterKeyClass) :
+							// Class.forName(adapterKeyClass);
+							if (bundle.getState() != Bundle.UNINSTALLED) {
+								aClass = bundle.loadClass(adapterKeyClass);
+							}
+							else {
+								aClass = Class.forName(adapterKeyClass);
+							}
+							if (aClass != null) {
+								useExtendedConstructor = true;
+								adapterKey = aClass;
+							}
+							else {
+								adapterKey = adapterKeyClass;
+							}
+						}
+						catch (Exception anyErrors) {
+							adapterKey = adapterKeyClass;
+						}
+					}
+
+					try {
+						Class theClass = null;
+						// Class theClass = classLoader != null ?
+						// classLoader.loadClass(className) :
+						// Class.forName(className);
+						if (bundle.getState() != Bundle.UNINSTALLED) {
+							theClass = bundle.loadClass(className);
+						}
+						else {
+							theClass = Class.forName(className);
+						}
+						if (useExtendedConstructor) {
+							java.lang.reflect.Constructor[] ctors = theClass.getConstructors();
+							for (int i = 0; i < ctors.length; i++) {
+								Class[] paramTypes = ctors[i].getParameterTypes();
+								if (ctors[i].isAccessible() && paramTypes.length == 2 && paramTypes[0].equals(Object.class) && paramTypes[1].equals(boolean.class)) {
+									try {
+										factory = (INodeAdapterFactory) ctors[i].newInstance(new Object[]{adapterKey, new Boolean(doRegisterAdapters)});
+									}
+									catch (IllegalAccessException e) {
+										// log for now, unless we find reason
+										// not to
+										Logger.log(Logger.INFO, e.getMessage());
+									}
+									catch (IllegalArgumentException e) {
+										// log for now, unless we find reason
+										// not to
+										Logger.log(Logger.INFO, e.getMessage());
+									}
+									catch (InstantiationException e) {
+										// log for now, unless we find reason
+										// not to
+										Logger.log(Logger.INFO, e.getMessage());
+									}
+									catch (InvocationTargetException e) {
+										// log for now, unless we find reason
+										// not to
+										Logger.log(Logger.INFO, e.getMessage());
+									}
+									catch (ExceptionInInitializerError e) {
+										// log or now, unless we find reason
+										// not to
+										Logger.log(Logger.INFO, e.getMessage());
+									}
+								}
+							}
+						}
+						if (factory == null) {
+							factory = (INodeAdapterFactory) element.createExecutableExtension(ATTR_CLASS);
+						}
+					}
+					catch (ClassNotFoundException e) {
+						// log or now, unless we find reason not to
+						Logger.log(Logger.INFO, e.getMessage());
+					}
+					catch (CoreException e) {
+						// log or now, unless we find reason not to
+						Logger.log(Logger.INFO, e.getMessage());
+					}
+				}
+			}
+		}
+		return factory;
+	}
+
+	protected List loadRegistry(Object contentType) {
+		List factoryList = new Vector();
+		IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
+		IExtensionPoint point = extensionRegistry.getExtensionPoint(SSECorePlugin.ID, EXTENSION_POINT_ID);
+		if (point != null) {
+			IConfigurationElement[] elements = point.getConfigurationElements();
+			for (int i = 0; i < elements.length; i++) {
+				INodeAdapterFactory factory = loadFactoryFromConfigurationElement(elements[i], contentType);
+				if (factory != null)
+					factoryList.add(factory);
+			}
+		}
+		return factoryList;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/NoCancelProgressMonitor.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/NoCancelProgressMonitor.java
new file mode 100644
index 0000000..c9f129f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/NoCancelProgressMonitor.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.sse.core.internal;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+
+
+public class NoCancelProgressMonitor extends NullProgressMonitor {
+
+
+	public NoCancelProgressMonitor() {
+		super();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.IProgressMonitor#isCanceled()
+	 */
+	public boolean isCanceled() {
+
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/NotImplementedException.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/NotImplementedException.java
new file mode 100644
index 0000000..3a0b985
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/NotImplementedException.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal;
+
+
+public class NotImplementedException extends RuntimeException {
+	/**
+	 * Comment for <code>serialVersionUID</code>
+	 */
+	private static final long serialVersionUID = 1L;
+
+	public NotImplementedException() {
+		super();
+	}
+
+	public NotImplementedException(String message) {
+		super(message);
+	}
+
+	public NotImplementedException(String message, Throwable cause) {
+		super(message, cause);
+	}
+
+	public NotImplementedException(Throwable cause) {
+		super(cause);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/NullMemento.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/NullMemento.java
new file mode 100644
index 0000000..9da4305
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/NullMemento.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal;
+
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.NonContentBasedEncodingRules;
+
+
+
+/**
+ * This class can be used in place of an EncodingMemento (its super class),
+ * when there is not in fact ANY encoding information. For example, when a
+ * structuredDocument is created directly from a String
+ */
+public class NullMemento extends EncodingMemento {
+	/**
+	 *  
+	 */
+	public NullMemento() {
+		super();
+		String defaultCharset = NonContentBasedEncodingRules.useDefaultNameRules(null);
+		setJavaCharsetName(defaultCharset);
+		setAppropriateDefault(defaultCharset);
+		setDetectedCharsetName(null);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/PropagatingAdapter.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/PropagatingAdapter.java
new file mode 100644
index 0000000..401c484
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/PropagatingAdapter.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal;
+
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
+
+public interface PropagatingAdapter extends INodeAdapter {
+
+	void addAdaptOnCreateFactory(INodeAdapterFactory factory);
+
+	List getAdaptOnCreateFactories();
+
+	/**
+	 * This method should be called immediately after adding a factory,
+	 * typically on the document (top level) node, so all nodes can be
+	 * adapted, if needed. This is needed for those occasions when a factory
+	 * is addeded after some nodes may have already been created at the time
+	 * the factory is added.
+	 */
+	void initializeForFactory(INodeAdapterFactory factory, INodeNotifier node);
+
+	// dmw: should have getFactoryFor?
+	void release();
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/PropagatingAdapterFactory.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/PropagatingAdapterFactory.java
new file mode 100644
index 0000000..70c84da
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/PropagatingAdapterFactory.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal;
+
+
+
+import java.util.ArrayList;
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+
+
+
+public interface PropagatingAdapterFactory extends INodeAdapterFactory {
+
+	void addContributedFactories(INodeAdapterFactory factory);
+
+	void setContributedFactories(ArrayList list);
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/SSECoreMessages.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/SSECoreMessages.java
new file mode 100644
index 0000000..4546839
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/SSECoreMessages.java
@@ -0,0 +1,50 @@
+/**********************************************************************
+ * Copyright (c) 2005, 2010 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 - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.sse.core.internal;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Strings used by SSE Core
+ * 
+ * @plannedfor 1.0
+ */
+public class SSECoreMessages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.wst.sse.core.internal.SSECorePluginResources";//$NON-NLS-1$
+
+	static {
+		// load message values from bundle file
+		NLS.initializeMessages(BUNDLE_NAME, SSECoreMessages.class);
+	}
+
+	private SSECoreMessages() {
+		// cannot create new instance
+	}
+
+	public static String A_model_s_id_can_not_be_nu_EXC_;
+	public static String Program_Error__ModelManage_EXC_;
+	public static String Original_Error__UI_;
+	public static String Text_Change_UI_;
+	public static String TaskScanner_0;
+	public static String TaskScanningJob_0;
+	public static String TaskScanningJob_1;
+	public static String Migrate_Charset;
+	
+	public static String IndexManager_0_starting;
+	public static String IndexManager_0_starting_1;
+	public static String IndexManager_0_Indexing_1_Files;	
+	public static String IndexManager_processing_deferred_resource_changes;
+	public static String IndexManager_Processing_entire_workspace_for_the_first_time;
+	public static String IndexManager_0_Processing_entire_workspace_for_the_first_time;
+	public static String IndexManager_processing_recent_resource_changes;
+	public static String IndexManager_0_resources_to_go_1;
+	public static String IndexManager_Waiting_for_0;
+	public static String IndexManager_0_Processing_resource_events;
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/SSECorePlugin.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/SSECorePlugin.java
new file mode 100644
index 0000000..15e32bb
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/SSECorePlugin.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal;
+
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry;
+import org.eclipse.wst.sse.core.internal.preferences.CommonModelPreferenceNames;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.tasks.TaskScanningScheduler;
+import org.osgi.framework.BundleContext;
+
+
+/**
+ * SSE Core Plugin.
+ */
+public class SSECorePlugin extends Plugin {
+	static SSECorePlugin instance = null;
+
+	public static final String ID = "org.eclipse.wst.sse.core"; //$NON-NLS-1$
+
+	public static SSECorePlugin getDefault() {
+		return instance;
+	}
+
+	public SSECorePlugin() {
+		super();
+		instance = this;
+	}
+
+	/**
+	 * Set default non-UI
+	 */
+	protected void initializeDefaultPluginPreferences() {
+		Preferences prefs = getDefault().getPluginPreferences();
+		// set model preference defaults
+
+		prefs.setDefault(CommonEncodingPreferenceNames.USE_3BYTE_BOM_WITH_UTF8, false);
+		
+		prefs.setDefault(CommonModelPreferenceNames.TASK_TAG_ENABLE, false);
+		prefs.setDefault(CommonModelPreferenceNames.TASK_TAG_TAGS, "TODO,FIXME,XXX"); //$NON-NLS-1$
+		prefs.setDefault(CommonModelPreferenceNames.TASK_TAG_PRIORITIES, "1,2,1"); //$NON-NLS-1$
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext context) throws Exception {
+		savePluginPreferences();
+		
+		TaskScanningScheduler.shutdown();
+
+		FileBufferModelManager.shutdown();
+
+		super.stop(context);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.Plugin#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+
+		// initialize FileBuffer handling
+		FileBufferModelManager.startup();
+
+		/**
+		 * If the user starts the workbench with
+		 * -Dorg.eclipse.wst.sse.core.taskscanner=off, the scanner should be
+		 * disabled
+		 */
+		String scan = System.getProperty("org.eclipse.wst.sse.core.taskscanner"); //$NON-NLS-1$
+		if (scan == null || !scan.equalsIgnoreCase("off")) { //$NON-NLS-1$
+			TaskScanningScheduler.startup();
+		}
+	}
+
+	/**
+	 * @deprecated
+	 */
+	public ModelHandlerRegistry getModelHandlerRegistry() {
+		return ModelHandlerRegistry.getInstance();
+	}
+
+	/**
+	 * @deprecated - use StructuredModelManager.getModelManager();
+	 */
+	public IModelManager getModelManager() {
+		return StructuredModelManager.getModelManager();
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/SSECorePluginResources.properties b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/SSECorePluginResources.properties
new file mode 100644
index 0000000..971c0f7
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/SSECorePluginResources.properties
@@ -0,0 +1,32 @@
+###############################################################################
+# Copyright (c) 2001, 2010 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
+#     Jens Lukowski/Innoopract - initial renaming/restructuring
+#
+###############################################################################
+A_model_s_id_can_not_be_nu_EXC_=A model's id can not be null
+Program_Error__ModelManage_EXC_=Program Error: ModelManagerImpl::saveModel. Model should be in the cache
+Original_Error__UI_=Original Error:
+Text_Change_UI_=Text Change
+TaskScanner_0=Scanning for Tasks
+TaskScanningJob_0=Scanning
+TaskScanningJob_1=Errors while detecting Tasks
+###############################################################################
+Migrate_Charset=Migrate Charset
+
+IndexManager_0_starting={0}: Starting
+IndexManager_0_starting_1={0}: Starting: {1}
+IndexManager_0_Indexing_1_Files={0}: Indexing {1} Files
+IndexManager_processing_deferred_resource_changes=Processing deferred resource changes
+IndexManager_Processing_entire_workspace_for_the_first_time=Processing entire workspace for the first time
+IndexManager_0_Processing_entire_workspace_for_the_first_time={0}: Processing entire workspace for the first time
+IndexManager_processing_recent_resource_changes=Processing recent resource changes
+IndexManager_0_resources_to_go_1={0} resources to index: {1}
+IndexManager_Waiting_for_0=Waiting for {0}
+IndexManager_0_Processing_resource_events={0}: Processing Resource Events
\ No newline at end of file
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/AbstractStructuredCleanupProcessor.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/AbstractStructuredCleanupProcessor.java
new file mode 100644
index 0000000..f525d5f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/AbstractStructuredCleanupProcessor.java
@@ -0,0 +1,464 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.cleanup;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Map;
+import java.util.Vector;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentRewriteSession;
+import org.eclipse.jface.text.DocumentRewriteSessionType;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.format.IStructuredFormatProcessor;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+
+public abstract class AbstractStructuredCleanupProcessor implements IStructuredCleanupProcessor {
+	public boolean refreshCleanupPreferences = true; // special flag for JUnit
+
+	// tests to skip refresh
+	// of cleanup preferences
+	// when it's set to false
+
+	public String cleanupContent(String input) throws IOException, CoreException {
+		IStructuredModel structuredModel = null;
+		InputStream inputStream = null;
+		try {
+			// setup structuredModel
+			inputStream = new ByteArrayInputStream(input.getBytes("UTF8")); //$NON-NLS-1$
+			String id = inputStream.toString() + getContentType();
+			structuredModel = StructuredModelManager.getModelManager().getModelForRead(id, inputStream, null);
+
+			// cleanup
+			cleanupModel(structuredModel, 0, structuredModel.getStructuredDocument().getLength());
+
+			// return output
+			return structuredModel.getStructuredDocument().get();
+		} finally {
+			ensureClosed(null, inputStream);
+			// release from model manager
+			if (structuredModel != null)
+				structuredModel.releaseFromRead();
+		}
+	}
+
+	public String cleanupContent(String input, int start, int length) throws IOException, CoreException {
+		IStructuredModel structuredModel = null;
+		InputStream inputStream = null;
+		try {
+			// setup structuredModel
+			inputStream = new ByteArrayInputStream(input.getBytes("UTF8")); //$NON-NLS-1$
+			String id = inputStream.toString() + getContentType();
+			structuredModel = StructuredModelManager.getModelManager().getModelForRead(id, inputStream, null);
+
+			// cleanup
+			cleanupModel(structuredModel, start, length);
+
+			// return output
+			return structuredModel.getStructuredDocument().get();
+		} finally {
+			ensureClosed(null, inputStream);
+			// release from model manager
+			if (structuredModel != null)
+				structuredModel.releaseFromRead();
+		}
+	}
+
+	public void cleanupDocument(IDocument document) throws IOException, CoreException {
+		if (document == null)
+			return;
+
+		IStructuredModel structuredModel = null;
+		// OutputStream outputStream = null;
+		try {
+			// setup structuredModel
+			// Note: We are getting model for edit. Will save model if model
+			// changed.
+			structuredModel = StructuredModelManager.getModelManager().getExistingModelForEdit(document);
+
+			// cleanup
+			cleanupModel(structuredModel);
+
+			// save model if needed
+			if (!structuredModel.isSharedForEdit() && structuredModel.isSaveNeeded())
+				structuredModel.save();
+		} finally {
+			// ensureClosed(outputStream, null);
+			// release from model manager
+			if (structuredModel != null)
+				structuredModel.releaseFromEdit();
+		}
+	}
+
+	public void cleanupDocument(IDocument document, int start, int length) throws IOException, CoreException {
+		if (document == null)
+			return;
+
+		if (start >= 0 && length >= 0 && start + length <= document.getLength()) {
+			IStructuredModel structuredModel = null;
+			// OutputStream outputStream = null;
+			try {
+				// setup structuredModel
+				// Note: We are getting model for edit. Will save model if
+				// model changed.
+				structuredModel = StructuredModelManager.getModelManager().getExistingModelForEdit(document);
+
+				// cleanup
+				cleanupModel(structuredModel, start, length);
+
+				// save model if needed
+				if (!structuredModel.isSharedForEdit() && structuredModel.isSaveNeeded())
+					structuredModel.save();
+			} finally {
+				// ensureClosed(outputStream, null);
+				// release from model manager
+				if (structuredModel != null)
+					structuredModel.releaseFromEdit();
+			}
+		}
+	}
+
+	public void cleanupFile(IFile file) throws IOException, CoreException {
+		IStructuredModel structuredModel = null;
+		// OutputStream outputStream = null;
+		try {
+			// setup structuredModel
+			structuredModel = StructuredModelManager.getModelManager().getModelForRead(file);
+
+			// cleanup
+			cleanupModel(structuredModel, 0, structuredModel.getStructuredDocument().getLength());
+
+			// save output to file
+			// outputStream = new
+			// FileOutputStream(file.getLocation().toString());
+			structuredModel.save(file);
+		} finally {
+			// ensureClosed(outputStream, null);
+			// release from model manager
+			if (structuredModel != null)
+				structuredModel.releaseFromRead();
+		}
+	}
+
+	public void cleanupFile(IFile file, int start, int length) throws IOException, CoreException {
+		IStructuredModel structuredModel = null;
+		// OutputStream outputStream = null;
+		try {
+			// setup structuredModel
+			structuredModel = StructuredModelManager.getModelManager().getModelForRead(file);
+
+			// cleanup
+			cleanupModel(structuredModel, start, length);
+
+			// save output to file
+			// outputStream = new
+			// FileOutputStream(file.getLocation().toString());
+			structuredModel.save(file);
+		} finally {
+			// ensureClosed(outputStream, null);
+			// release from model manager
+			if (structuredModel != null)
+				structuredModel.releaseFromRead();
+		}
+	}
+
+	public void cleanupFileName(String fileName) throws IOException, CoreException {
+		IStructuredModel structuredModel = null;
+		InputStream inputStream = null;
+		// OutputStream outputStream = null;
+		try {
+			// setup structuredModel
+			inputStream = new FileInputStream(fileName);
+			structuredModel = StructuredModelManager.getModelManager().getModelForRead(fileName, inputStream, null);
+
+			// cleanup
+			cleanupModel(structuredModel, 0, structuredModel.getStructuredDocument().getLength());
+
+			// save output to file
+			// outputStream = new FileOutputStream(fileName);
+			structuredModel.save();
+		} finally {
+			// ensureClosed(outputStream, inputStream);
+			// release from model manager
+			if (structuredModel != null)
+				structuredModel.releaseFromRead();
+		}
+	}
+
+	public void cleanupFileName(String fileName, int start, int length) throws IOException, CoreException {
+		IStructuredModel structuredModel = null;
+		InputStream inputStream = null;
+		// OutputStream outputStream = null;
+		try {
+			// setup structuredModel
+			inputStream = new FileInputStream(fileName);
+			structuredModel = StructuredModelManager.getModelManager().getModelForRead(fileName, inputStream, null);
+
+			// cleanup
+			cleanupModel(structuredModel, start, length);
+
+			// save output to file
+			// outputStream = new FileOutputStream(fileName);
+			structuredModel.save();
+		} finally {
+			// ensureClosed(outputStream, inputStream);
+			// release from model manager
+			if (structuredModel != null)
+				structuredModel.releaseFromRead();
+		}
+	}
+
+	public void cleanupModel(IStructuredModel structuredModel) {
+
+		int start = 0;
+		int length = structuredModel.getStructuredDocument().getLength();
+		cleanupModel(structuredModel, start, length);
+	}
+
+	public void cleanupModel(IStructuredModel structuredModel, int start, int length) {
+
+		if (structuredModel != null) {
+			if ((start >= 0) && (length <= structuredModel.getStructuredDocument().getLength())) {
+				Vector activeNodes = getActiveNodes(structuredModel, start, length);
+				if (activeNodes.size() > 0) {
+					Node firstNode = (Node) activeNodes.firstElement();
+					Node lastNode = (Node) activeNodes.lastElement();
+					boolean done = false;
+					Node eachNode = firstNode;
+					Node nextNode = null;
+
+					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=123621
+					// if doing any sort of cleanup, set up rewrite session/modelchanged
+					IDocumentExtension4 docExt4 = null;
+					if (structuredModel.getStructuredDocument() instanceof IDocumentExtension4) {
+						docExt4 = (IDocumentExtension4) structuredModel.getStructuredDocument();
+					}
+					DocumentRewriteSession rewriteSession = null;
+
+					try {
+						// whenever formatting model, fire
+						// abouttochange/modelchanged
+						structuredModel.aboutToChangeModel();
+						rewriteSession = (docExt4 == null || docExt4.getActiveRewriteSession() != null) ? null : docExt4.startRewriteSession(DocumentRewriteSessionType.UNRESTRICTED);
+
+						while (!done) {
+							// update "done"
+							done = (eachNode == lastNode);
+
+						// get next sibling before cleanup because eachNode
+							// may
+							// be deleted,
+							// for example when it's an empty text node
+							nextNode = eachNode.getNextSibling();
+
+							// cleanup selected node(s)
+							cleanupNode(eachNode);
+
+							// update each node
+							if (nextNode != null && nextNode.getParentNode() == null)
+								// nextNode is deleted during cleanup
+								eachNode = eachNode.getNextSibling();
+							else
+								eachNode = nextNode;
+
+							// This should not be needed, but just in case
+							// something went wrong with with eachNode.
+							// We don't want an infinite loop here.
+							if (eachNode == null)
+								done = true;
+						}
+
+						// format source
+						if (getFormatSourcePreference(structuredModel)) {
+							// format the document
+							IStructuredFormatProcessor formatProcessor = getFormatProcessor();
+							formatProcessor.formatModel(structuredModel);
+						}
+					}
+					finally {
+						// we need two finally's, just in case first fails
+						try {
+							if ((docExt4 != null) && (rewriteSession != null))
+								docExt4.stopRewriteSession(rewriteSession);
+						}
+						finally {
+							// always make sure to fire changedmodel when done
+							structuredModel.changedModel();
+						}
+					}
+				}
+			}
+		}
+	}
+
+	public void cleanupNode(Node node) {
+		if (node != null) {
+			Node cleanupNode = node;
+
+			// cleanup the owner node if it's an attribute node
+			if (cleanupNode.getNodeType() == Node.ATTRIBUTE_NODE)
+				cleanupNode = ((Attr) cleanupNode).getOwnerElement();
+
+			// refresh cleanup preferences before getting cleanup handler
+			if (refreshCleanupPreferences)
+				refreshCleanupPreferences();
+
+			// get cleanup handler
+			IStructuredCleanupHandler cleanupHandler = getCleanupHandler(cleanupNode);
+			if (cleanupHandler != null) {
+				// cleanup each node
+				cleanupHandler.cleanup(cleanupNode);
+			}
+		}
+	}
+
+	protected void convertLineDelimiters(IDocument document, String newDelimiter) {
+		final int lineCount = document.getNumberOfLines();
+		Map partitioners = TextUtilities.removeDocumentPartitioners(document);
+		try {
+			for (int i = 0; i < lineCount; i++) {
+				final String delimiter = document.getLineDelimiter(i);
+				if (delimiter != null && delimiter.length() > 0 && !delimiter.equals(newDelimiter)) {
+					IRegion region = document.getLineInformation(i);
+					document.replace(region.getOffset() + region.getLength(), delimiter.length(), newDelimiter);
+				}
+			}
+		} catch (BadLocationException e) {
+			Logger.logException(e);
+		} finally {
+			TextUtilities.addDocumentPartitioners(document, partitioners);
+		}
+	}
+
+	protected void ensureClosed(OutputStream outputStream, InputStream inputStream) {
+		try {
+			if (inputStream != null) {
+				inputStream.close();
+			}
+		} catch (IOException e) {
+			Logger.logException(e); // hopeless
+		}
+		try {
+			if (outputStream != null) {
+				outputStream.close();
+			}
+		} catch (IOException e) {
+			Logger.logException(e); // hopeless
+		}
+	}
+
+	protected Vector getActiveNodes(IStructuredModel structuredModel, int startNodeOffset, int length) {
+		Vector activeNodes = new Vector();
+
+		if (structuredModel != null) {
+			Node startNode = (Node) structuredModel.getIndexedRegion(startNodeOffset);
+			Node endNode = (Node) structuredModel.getIndexedRegion(startNodeOffset + length);
+
+			// make sure it's an non-empty document
+			if (startNode != null) {
+				while (isSiblingOf(startNode, endNode) == false) {
+					if (endNode != null)
+						endNode = endNode.getParentNode();
+					if (endNode == null) {
+						startNode = startNode.getParentNode();
+						endNode = (Node) structuredModel.getIndexedRegion(startNodeOffset + length);
+					}
+				}
+
+				while (startNode != endNode) {
+					activeNodes.addElement(startNode);
+					startNode = startNode.getNextSibling();
+				}
+				if (startNode != null)
+					activeNodes.addElement(startNode);
+			}
+		}
+
+		return activeNodes;
+	}
+
+	abstract protected IStructuredCleanupHandler getCleanupHandler(Node node);
+
+	abstract protected String getContentType();
+
+	protected boolean getConvertEOLCodesPreference(IStructuredModel structuredModel) {
+
+		boolean convertEOLCodes = true;
+		IStructuredCleanupHandler cleanupHandler = getCleanupHandler((Node) structuredModel.getIndexedRegion(0));
+		if (cleanupHandler != null) {
+			IStructuredCleanupPreferences cleanupPreferences = cleanupHandler.getCleanupPreferences();
+			convertEOLCodes = cleanupPreferences.getConvertEOLCodes();
+		}
+		return convertEOLCodes;
+	}
+
+	protected String getEOLCodePreference(IStructuredModel structuredModel) {
+
+		IScopeContext[] scopeContext = new IScopeContext[]{new InstanceScope()};
+		String eolCode = Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext);
+
+		IStructuredCleanupHandler cleanupHandler = getCleanupHandler((Node) structuredModel.getIndexedRegion(0));
+		if (cleanupHandler != null) {
+			IStructuredCleanupPreferences cleanupPreferences = cleanupHandler.getCleanupPreferences();
+			eolCode = cleanupPreferences.getEOLCode();
+		}
+		return eolCode;
+	}
+
+	abstract protected IStructuredFormatProcessor getFormatProcessor();
+
+	protected boolean getFormatSourcePreference(IStructuredModel structuredModel) {
+
+		boolean formatSource = true;
+		IStructuredCleanupHandler cleanupHandler = getCleanupHandler((Node) structuredModel.getIndexedRegion(0));
+		if (cleanupHandler != null) {
+			IStructuredCleanupPreferences cleanupPreferences = cleanupHandler.getCleanupPreferences();
+			formatSource = cleanupPreferences.getFormatSource();
+		}
+		return formatSource;
+	}
+
+	protected boolean isSiblingOf(Node node, Node endNode) {
+		if (endNode == null) {
+			return true;
+		} else {
+			Node siblingNode = node;
+			while (siblingNode != null) {
+				if (siblingNode == endNode)
+					return true;
+				else
+					siblingNode = siblingNode.getNextSibling();
+			}
+			return false;
+		}
+	}
+
+	abstract protected void refreshCleanupPreferences();
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/IStructuredCleanupHandler.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/IStructuredCleanupHandler.java
new file mode 100644
index 0000000..4f98956
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/IStructuredCleanupHandler.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.cleanup;
+
+import org.w3c.dom.Node;
+
+public interface IStructuredCleanupHandler {
+	Node cleanup(Node node);
+
+	IStructuredCleanupPreferences getCleanupPreferences();
+
+	void setCleanupPreferences(IStructuredCleanupPreferences cleanupPreferences);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/IStructuredCleanupPreferences.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/IStructuredCleanupPreferences.java
new file mode 100644
index 0000000..7f5058d
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/IStructuredCleanupPreferences.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.cleanup;
+
+import org.eclipse.core.runtime.Preferences;
+
+public interface IStructuredCleanupPreferences {
+
+	int getAttrNameCase();
+
+	boolean getCompressEmptyElementTags();
+
+	boolean getConvertEOLCodes();
+
+	String getEOLCode();
+
+	boolean getFormatSource();
+
+	boolean getInsertMissingTags();
+
+	boolean getInsertRequiredAttrs();
+
+	boolean getQuoteAttrValues();
+
+	int getTagNameCase();
+
+	void setAttrNameCase(int attrNameCase);
+
+	void setCompressEmptyElementTags(boolean compressEmptyElementTags);
+
+	void setConvertEOLCodes(boolean convertEOLCodes);
+
+	void setEOLCode(String EOLCode);
+
+	void setFormatSource(boolean formatSource);
+
+	void setInsertMissingTags(boolean insertMissingTags);
+
+	void setInsertRequiredAttrs(boolean insertRequiredAttrs);
+
+	void setPreferences(Preferences preferences);
+
+	void setQuoteAttrValues(boolean quoteAttrValues);
+
+	void setTagNameCase(int tagNameCase);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/IStructuredCleanupProcessor.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/IStructuredCleanupProcessor.java
new file mode 100644
index 0000000..27bce4c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/IStructuredCleanupProcessor.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.cleanup;
+
+import java.io.IOException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.w3c.dom.Node;
+
+/**
+ * This interface and related classes are 'internal' and should not 
+ * be treated as API, even though used across components in WTP. 
+ * Consider it a work in progress.
+ */
+
+public interface IStructuredCleanupProcessor {
+	/**
+	 * This form of the CleanupProcessor takes an input string as input,
+	 * creates an InputStream from the input string, create a temporary model
+	 * of the content type specified, cleanups the whole model, then returns
+	 * the cleaned up input string.
+	 */
+	String cleanupContent(String content) throws IOException, CoreException;
+
+	/**
+	 * This form of the CleanupProcessor takes an input string as input,
+	 * creates an InputStream from the input string, create a temporary model
+	 * of the content type specified, cleanups the model within start and
+	 * length, then returns the cleaned up input string.
+	 */
+	String cleanupContent(String content, int start, int length) throws IOException, CoreException;
+
+	/**
+	 * This form of the CleanupProcessor takes an IDocument as input, creates
+	 * a temporary model of content type calculated using the IDocument's file
+	 * extension, cleanups the whole model, then releases the model.
+	 */
+	void cleanupDocument(IDocument document) throws IOException, CoreException;
+
+	/**
+	 * This form of the CleanupProcessor takes an IDocument as input, creates
+	 * a temporary model of content type calculated using the IDocument's file
+	 * extension, cleanups the model within start and length, then releases
+	 * the model.
+	 */
+	void cleanupDocument(IDocument document, int start, int length) throws IOException, CoreException;
+
+	/**
+	 * This form of the CleanupProcessor takes an IFile as input, creates a
+	 * temporary model of content type calculated using the IFile's file
+	 * extension, cleanups the whole model, then releases the model. The IFile
+	 * is updated when the last reference of the model is released in the
+	 * model manager.
+	 */
+	void cleanupFile(IFile file) throws IOException, CoreException;
+
+	/**
+	 * This form of the CleanupProcessor takes an IFile as input, creates a
+	 * temporary model of content type calculated using the IFile's file
+	 * extension, cleanups the model within start and length, then releases
+	 * the model. The IFile is updated when the last reference of the model is
+	 * released in the model manager.
+	 */
+	void cleanupFile(IFile file, int start, int length) throws IOException, CoreException;
+
+	/**
+	 * This form of the CleanupProcessor takes a file name as input,creates an
+	 * InputStream from the file, create a temporary model of content type
+	 * calculated using the file name's file extension, cleanups the whole
+	 * model, then releases the model. The file is updated when the last
+	 * reference of the model is released in the model manager.
+	 */
+	void cleanupFileName(String fileName) throws IOException, CoreException;
+
+	/**
+	 * This form of the CleanupProcessor takes a file name as input,creates an
+	 * InputStream from the file, create a temporary model of content type
+	 * calculated using the file name's file extension, cleanups the model
+	 * within start and length, then releases the model. The file is updated
+	 * when the last reference of the model is released in the model manager.
+	 */
+	void cleanupFileName(String fileName, int start, int length) throws IOException, CoreException;
+
+	/**
+	 * This form of the CleanupProcessor takes a model as input, and cleanups
+	 * the whole model.
+	 */
+	void cleanupModel(IStructuredModel structuredModel);
+
+	/**
+	 * This form of the CleanupProcessor takes a model as input, and cleanups
+	 * the model within start and length.
+	 */
+	void cleanupModel(IStructuredModel structuredModel, int start, int length);
+
+	/**
+	 * This form of the CleanupProcessor takes a node as input, and formats
+	 * the node and all its children.
+	 */
+	void cleanupNode(Node node);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/StructuredCleanupPreferences.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/StructuredCleanupPreferences.java
new file mode 100644
index 0000000..a834418
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/StructuredCleanupPreferences.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.cleanup;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.wst.sse.core.internal.SSECorePlugin;
+
+
+public class StructuredCleanupPreferences implements IStructuredCleanupPreferences {
+	private int fAttrNameCase;
+	private boolean fCompressEmptyElementTags;
+	private boolean fConvertEOLCodes;
+	private String fEOLCode;
+	private boolean fFormatSource;
+	private boolean fInsertMissingTags;
+	private boolean fInsertRequiredAttrs;
+	//private IPreferenceStore fPreferenceStore = null;
+	private Preferences fPreferences = null;
+	private boolean fQuoteAttrValues;
+
+	private int fTagNameCase;
+
+	public int getAttrNameCase() {
+
+		return fAttrNameCase;
+	}
+
+	public boolean getCompressEmptyElementTags() {
+
+		return fCompressEmptyElementTags;
+	}
+
+	public boolean getConvertEOLCodes() {
+
+		return fConvertEOLCodes;
+	}
+
+	public String getEOLCode() {
+
+		return fEOLCode;
+	}
+
+	public boolean getFormatSource() {
+
+		return fFormatSource;
+	}
+
+	public boolean getInsertMissingTags() {
+
+		return fInsertMissingTags;
+	}
+
+	public boolean getInsertRequiredAttrs() {
+
+		return fInsertRequiredAttrs;
+	}
+
+	public Preferences getPreferences() {
+
+		if (fPreferences == null) {
+			fPreferences = SSECorePlugin.getDefault().getPluginPreferences();
+		}
+		return fPreferences;
+	}
+
+	public boolean getQuoteAttrValues() {
+
+		return fQuoteAttrValues;
+	}
+
+	public int getTagNameCase() {
+
+		return fTagNameCase;
+	}
+
+	public void setAttrNameCase(int attrNameCase) {
+
+		fAttrNameCase = attrNameCase;
+	}
+
+	public void setCompressEmptyElementTags(boolean compressEmptyElementTags) {
+
+		fCompressEmptyElementTags = compressEmptyElementTags;
+	}
+
+	public void setConvertEOLCodes(boolean convertEOLCodes) {
+
+		fConvertEOLCodes = convertEOLCodes;
+	}
+
+	public void setEOLCode(String EOLCode) {
+
+		fEOLCode = EOLCode;
+	}
+
+	public void setFormatSource(boolean formatSource) {
+
+		fFormatSource = formatSource;
+	}
+
+	public void setInsertMissingTags(boolean insertMissingTags) {
+
+		fInsertMissingTags = insertMissingTags;
+	}
+
+	public void setInsertRequiredAttrs(boolean insertRequiredAttrs) {
+
+		fInsertRequiredAttrs = insertRequiredAttrs;
+	}
+
+	public void setPreferences(Preferences prefs) {
+
+		fPreferences = prefs;
+	}
+
+	public void setQuoteAttrValues(boolean quoteAttrValues) {
+
+		fQuoteAttrValues = quoteAttrValues;
+	}
+
+	public void setTagNameCase(int tagNameCase) {
+
+		fTagNameCase = tagNameCase;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/StructuredContentCleanupHandler.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/StructuredContentCleanupHandler.java
new file mode 100644
index 0000000..6c06ca0
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/StructuredContentCleanupHandler.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.cleanup;
+
+public interface StructuredContentCleanupHandler {
+
+	IStructuredCleanupProcessor getCleanupProcessor(String contentType);
+
+	void setCleanupProcessor(IStructuredCleanupProcessor cleanupProcessor, String contentType);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/StructuredContentCleanupHandlerImpl.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/StructuredContentCleanupHandlerImpl.java
new file mode 100644
index 0000000..27a6246
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/cleanup/StructuredContentCleanupHandlerImpl.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.cleanup;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jface.text.Assert;
+
+public class StructuredContentCleanupHandlerImpl implements StructuredContentCleanupHandler {
+	protected Map fCleanupProcessors;
+
+	public IStructuredCleanupProcessor getCleanupProcessor(String contentType) {
+		Assert.isNotNull(contentType);
+
+		if (fCleanupProcessors == null)
+			return null;
+
+		return (IStructuredCleanupProcessor) fCleanupProcessors.get(contentType);
+	}
+
+	public void setCleanupProcessor(IStructuredCleanupProcessor cleanupProcessor, String contentType) {
+		Assert.isNotNull(contentType);
+
+		if (fCleanupProcessors == null)
+			fCleanupProcessors = new HashMap();
+
+		if (fCleanupProcessors == null)
+			fCleanupProcessors.remove(contentType);
+		else
+			fCleanupProcessors.put(contentType, cleanupProcessor);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/AbstractDocumentLoader.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/AbstractDocumentLoader.java
new file mode 100644
index 0000000..ea9959e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/AbstractDocumentLoader.java
@@ -0,0 +1,438 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.document;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+import org.eclipse.wst.sse.core.internal.encoding.CodedReaderCreator;
+import org.eclipse.wst.sse.core.internal.encoding.ContentTypeEncodingPreferences;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingRule;
+import org.eclipse.wst.sse.core.internal.exceptions.MalformedInputExceptionWithDetail;
+import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredPartitioning;
+
+
+
+/**
+ * This class reads a file and creates an Structured Model.
+ */
+public abstract class AbstractDocumentLoader implements IDocumentLoader {
+
+	private CodedReaderCreator fCodedReaderCreator;
+	protected IDocumentCharsetDetector fDocumentEncodingDetector;
+	// private boolean fPropertiesObtained;
+
+	protected EncodingMemento fEncodingMemento;
+	protected Reader fFullPreparedReader;
+
+	/**
+	 * AbstractLoader constructor also initializes encoding converter/mapper
+	 */
+	public AbstractDocumentLoader() {
+		super();
+	}
+
+	protected final StringBuffer convertLineDelimiters(StringBuffer allTextBuffer, String lineDelimiterToUse) {
+		// TODO: avoid use of String instance
+		String allText = allTextBuffer.toString();
+		IDocument tempDoc = new Document(allText);
+		if (lineDelimiterToUse == null)
+			lineDelimiterToUse = System.getProperty("line.separator"); //$NON-NLS-1$
+		StringBuffer newText = new StringBuffer();
+		int lineCount = tempDoc.getNumberOfLines();
+		for (int i = 0; i < lineCount; i++) {
+			try {
+				org.eclipse.jface.text.IRegion lineInfo = tempDoc.getLineInformation(i);
+				int lineStartOffset = lineInfo.getOffset();
+				int lineLength = lineInfo.getLength();
+				int lineEndOffset = lineStartOffset + lineLength;
+				newText.append(allText.substring(lineStartOffset, lineEndOffset));
+				if ((i < lineCount - 1) && (tempDoc.getLineDelimiter(i) != null))
+					newText.append(lineDelimiterToUse);
+			}
+			catch (org.eclipse.jface.text.BadLocationException exception) {
+				// should fix up to either throw nothing, or the right thing,
+				// but
+				// in the course of refactoring, this was easiest "quick fix".
+				throw new RuntimeException(exception);
+			}
+		}
+		return newText;
+	}
+
+	/**
+	 * This method must return a new instance of IEncodedDocument, that has
+	 * been initialized with appropriate parser. For many loaders, the
+	 * (default) parser used is known for any input. For others, the correct
+	 * parser (and its initialization) is normally dependent on the content of
+	 * the file. This no-argument method should assume "empty input" and would
+	 * therefore return the default parser for the default contentType.
+	 */
+	public IEncodedDocument createNewStructuredDocument() {
+		IEncodedDocument structuredDocument = newEncodedDocument();
+		// Make sure every structuredDocument has an Encoding Memento,
+		// which is the default one for "empty" structuredDocuments
+		String charset = ContentTypeEncodingPreferences.useDefaultNameRules(getDocumentEncodingDetector());
+		String specDefaultCharset = getDocumentEncodingDetector().getSpecDefaultEncoding();
+		structuredDocument.setEncodingMemento(CodedIO.createEncodingMemento(charset, EncodingMemento.DEFAULTS_ASSUMED_FOR_EMPTY_INPUT, specDefaultCharset));
+
+		String lineDelimiter = getPreferredNewLineDelimiter(null);
+		if (lineDelimiter != null)
+			structuredDocument.setPreferredLineDelimiter(lineDelimiter);
+
+		IDocumentPartitioner defaultPartitioner = getDefaultDocumentPartitioner();
+		if (structuredDocument instanceof IDocumentExtension3) {
+			((IDocumentExtension3) structuredDocument).setDocumentPartitioner(IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING, defaultPartitioner);
+		}
+		else {
+			structuredDocument.setDocumentPartitioner(defaultPartitioner);
+		}
+		defaultPartitioner.connect(structuredDocument);
+
+		return structuredDocument;
+	}
+
+	/**
+	 * This abstract version should handle most cases, but won't if
+	 * contentType is sensitive to encoding, and/or embedded types
+	 */
+	public IEncodedDocument createNewStructuredDocument(IFile iFile) throws IOException, CoreException {
+		IEncodedDocument structuredDocument = createNewStructuredDocument();
+
+		String lineDelimiter = getPreferredNewLineDelimiter(iFile);
+		if (lineDelimiter != null)
+			structuredDocument.setPreferredLineDelimiter(lineDelimiter);
+
+		try {
+
+			CodedReaderCreator creator = getCodedReaderCreator();
+			creator.set(iFile);
+			fEncodingMemento = creator.getEncodingMemento();
+			structuredDocument.setEncodingMemento(fEncodingMemento);
+			fFullPreparedReader = getCodedReaderCreator().getCodedReader();
+
+			setDocumentContentsFromReader(structuredDocument, fFullPreparedReader);
+		}
+		finally {
+			if (fFullPreparedReader != null) {
+				fFullPreparedReader.close();
+			}
+		}
+		return structuredDocument;
+	}
+
+	public IEncodedDocument createNewStructuredDocument(String filename, InputStream inputStream) throws UnsupportedEncodingException, IOException {
+		return createNewStructuredDocument(filename, inputStream, EncodingRule.CONTENT_BASED);
+	}
+
+	public IEncodedDocument createNewStructuredDocument(String filename, InputStream inputStream, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException {
+		if (filename == null && inputStream == null) {
+			throw new IllegalArgumentException("can not have both null filename and inputstream"); //$NON-NLS-1$
+		}
+		IEncodedDocument structuredDocument = createNewStructuredDocument();
+		CodedReaderCreator codedReaderCreator = getCodedReaderCreator();
+		try {
+			codedReaderCreator.set(filename, inputStream);
+			codedReaderCreator.setEncodingRule(encodingRule);
+			fEncodingMemento = codedReaderCreator.getEncodingMemento();
+			fFullPreparedReader = codedReaderCreator.getCodedReader();
+			structuredDocument.setEncodingMemento(fEncodingMemento);
+			setDocumentContentsFromReader(structuredDocument, fFullPreparedReader);
+		}
+		catch (CoreException e) {
+			// impossible in this context
+			throw new Error(e);
+		}
+		finally {
+			if (fFullPreparedReader != null) {
+				fFullPreparedReader.close();
+			}
+		}
+
+		return structuredDocument;
+	}
+
+	private int getCharPostionOfFailure(BufferedReader inputStream) {
+		int charPosition = 1;
+		int charRead = -1;
+		boolean errorFound = false;
+		do {
+			try {
+				charRead = inputStream.read();
+				charPosition++;
+			}
+			catch (IOException e) {
+				// this is expected, since we're expecting failure,
+				// so no need to do anything.
+				errorFound = true;
+				break;
+			}
+		}
+		while (!(charRead == -1 || errorFound));
+
+		if (errorFound)
+			// dmw, blindly modified to +1 to get unit tests to work, moving
+			// from Java 1.3, to 1.4
+			// not sure how/why this behavior would have changed. (Its as if
+			// 'read' is reporting error
+			// one character early).
+			return charPosition + 1;
+		else
+			return -1;
+	}
+
+	/**
+	 * @return Returns the codedReaderCreator.
+	 */
+	protected CodedReaderCreator getCodedReaderCreator() {
+		if (fCodedReaderCreator == null) {
+			fCodedReaderCreator = new CodedReaderCreator();
+		}
+		return fCodedReaderCreator;
+	}
+
+	/**
+	 * Creates the partitioner to be used with the
+	 * IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING partitioning
+	 * 
+	 * @return IDocumentPartitioner
+	 */
+	public abstract IDocumentPartitioner getDefaultDocumentPartitioner();
+
+	/**
+	 * Returns the encodingMemento.
+	 * 
+	 * @return EncodingMemento
+	 */
+	public EncodingMemento getEncodingMemento() {
+		if (fEncodingMemento == null) {
+			throw new IllegalStateException("Program Error: encodingMemento was accessed before it was set"); //$NON-NLS-1$
+		}
+		return fEncodingMemento;
+	}
+
+	/**
+	 * @return Returns the fullPreparedReader.
+	 */
+	protected Reader getFullPreparedReader() throws UnsupportedEncodingException, CoreException, IOException {
+		if (fFullPreparedReader == null) {
+			fFullPreparedReader = getCodedReaderCreator().getCodedReader();
+		}
+		return fFullPreparedReader;
+	}
+
+	/**
+	 * Returns the default line delimiter preference for the given file.
+	 * 
+	 * @param file
+	 *            the file
+	 * @return the default line delimiter
+	 * @since 3.1
+	 */
+	private String getPlatformLineDelimiterPreference(IFile file) {
+		IScopeContext[] scopeContext;
+		if (file != null && file.getProject() != null) {
+			// project preference
+			scopeContext = new IScopeContext[]{new ProjectScope(file.getProject())};
+			String lineDelimiter = Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext);
+			if (lineDelimiter != null)
+				return lineDelimiter;
+		}
+		// workspace preference
+		scopeContext = new IScopeContext[]{new InstanceScope()};
+		return Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext);
+	}
+
+	/**
+	 * @deprecated use getPreferredNewLineDelimiter(IFile) instead
+	 */
+	protected String getPreferredNewLineDelimiter() {
+		return getPreferredNewLineDelimiter(null);
+	}
+
+	/**
+	 * If subclass doesn't implement, return platform default
+	 */
+	protected String getPreferredNewLineDelimiter(IFile file) {
+		return getPlatformLineDelimiterPreference(file);
+	}
+
+	/**
+	 * A utility method, but depends on subclasses to impliment the preferred
+	 * end of line for a particular content type. Note: subclasses should not
+	 * re-implement this method (there's no reason to, even though its part of
+	 * interface). This method not only converts end-of-line characters, if
+	 * needed, but sets the correct end-of-line delimiter in
+	 * structuredDocument. Minor note: can't use this exact method in dumpers,
+	 * since the decision to change or not is a little different, and since
+	 * there we have to change text of structuredDocument if found to need
+	 * conversion. (Where as for loading, we assume we haven't yet set text in
+	 * structuredDocument, but will be done by other method just a tiny biy
+	 * later). Needs to be public to handle interface. It is in the interface
+	 * just so ModelManagerImpl can use it in a special circumstance.
+	 */
+	public StringBuffer handleLineDelimiter(StringBuffer originalString, IEncodedDocument theFlatModel) {
+		// TODO: need to handle line delimiters so Marker Positions are
+		// updated
+		StringBuffer convertedText = null;
+		// based on text, make a guess on what's being used as
+		// line delimiter
+		String probableLineDelimiter = TextUtilities.determineLineDelimiter(originalString, theFlatModel.getLegalLineDelimiters(), System.getProperty("line.separator")); //$NON-NLS-1$
+		String preferredLineDelimiter = getPreferredNewLineDelimiter(null);
+		if (preferredLineDelimiter == null) {
+			// when preferredLineDelimiter is null, it means "leave alone"
+			// so no conversion needed.
+			// set here, only if null (should already be set, but if not,
+			// we'll set so any subsequent editing inserts what we're
+			// assuming)
+			if (!theFlatModel.getPreferredLineDelimiter().equals(probableLineDelimiter)) {
+				theFlatModel.setPreferredLineDelimiter(probableLineDelimiter);
+			}
+			convertedText = originalString;
+		}
+		else {
+			if (!preferredLineDelimiter.equals(probableLineDelimiter)) {
+				// technically, wouldn't have to convert line delimiters
+				// here at beginning, but when we save, if the preferred
+				// line delimter is "leave alone" then we do leave alone,
+				// so best to be right from beginning.
+				convertedText = convertLineDelimiters(originalString, preferredLineDelimiter);
+				theFlatModel.setPreferredLineDelimiter(preferredLineDelimiter);
+			}
+			else {
+				// they are already the same, no conversion needed
+				theFlatModel.setPreferredLineDelimiter(preferredLineDelimiter);
+				convertedText = originalString;
+			}
+		}
+		return convertedText;
+	}
+
+	protected abstract IEncodedDocument newEncodedDocument();
+
+	/**
+	 * Very mechanical method, just to read the characters, once the reader is
+	 * correctly created. Can throw MalFormedInputException.
+	 */
+	private StringBuffer readInputStream(Reader reader) throws IOException {
+
+		int fBlocksRead = 0;
+		StringBuffer buffer = new StringBuffer();
+		int numRead = 0;
+		try {
+			char tBuff[] = new char[CodedIO.MAX_BUF_SIZE];
+			while (numRead != -1) {
+				numRead = reader.read(tBuff, 0, tBuff.length);
+				if (numRead > 0) {
+					buffer.append(tBuff, 0, numRead);
+					fBlocksRead++;
+				}
+			}
+		}
+		catch (MalformedInputException e) {
+			throw new MalformedInputExceptionWithDetail(fEncodingMemento.getJavaCharsetName(), fBlocksRead * CodedIO.MAX_BUF_SIZE + numRead + e.getInputLength());
+		}
+		catch (UnmappableCharacterException e) {
+			throw new MalformedInputExceptionWithDetail(fEncodingMemento.getJavaCharsetName(), fBlocksRead * CodedIO.MAX_BUF_SIZE + numRead + e.getInputLength());
+
+		}
+		return buffer;
+	}
+
+	public void reload(IEncodedDocument encodedDocument, Reader inputStreamReader) throws IOException {
+		if (inputStreamReader == null) {
+			throw new IllegalArgumentException("stream reader can not be null"); //$NON-NLS-1$
+		}
+		int READ_BUFFER_SIZE = 8192;
+		int MAX_BUFFERED_SIZE_FOR_RESET_MARK = 200000;
+		// temp .... eventually we'lll only read as needed
+		BufferedReader bufferedReader = new BufferedReader(inputStreamReader, MAX_BUFFERED_SIZE_FOR_RESET_MARK);
+		bufferedReader.mark(MAX_BUFFERED_SIZE_FOR_RESET_MARK);
+		StringBuffer buffer = new StringBuffer();
+		try {
+			int numRead = 0;
+			char tBuff[] = new char[READ_BUFFER_SIZE];
+			while ((numRead = bufferedReader.read(tBuff, 0, tBuff.length)) != -1) {
+				buffer.append(tBuff, 0, numRead);
+			}
+			// remember -- we didn't open stream ... so we don't close it
+		}
+		catch (MalformedInputException e) {
+			// int pos = e.getInputLength();
+			EncodingMemento localEncodingMemento = getEncodingMemento();
+			boolean couldReset = true;
+			String encodingNameInError = localEncodingMemento.getJavaCharsetName();
+			if (encodingNameInError == null) {
+				encodingNameInError = localEncodingMemento.getDetectedCharsetName();
+			}
+			try {
+				bufferedReader.reset();
+			}
+			catch (IOException resetException) {
+				// the only errro that can occur during reset is an
+				// IOException
+				// due to already being past the rest mark. In that case, we
+				// throw more generic message
+				couldReset = false;
+			}
+			// -1 can be used by UI layer as a code that "position could not
+			// be
+			// determined"
+			int charPostion = -1;
+			if (couldReset) {
+
+				charPostion = getCharPostionOfFailure(bufferedReader);
+				// getCharPostionOfFailure(new InputStreamReader(inStream,
+				// javaEncodingNameInError));
+			}
+			// all of that just to throw more accurate error
+			// note: we do the conversion to ianaName, instead of using the
+			// local
+			// variable,
+			// because this is ultimately only for the user error message
+			// (that
+			// is,
+			// the error occurred
+			// in context of javaEncodingName no matter what ianaEncodingName
+			// is
+			throw new MalformedInputExceptionWithDetail(encodingNameInError, CodedIO.getAppropriateJavaCharset(encodingNameInError), charPostion, !couldReset, MAX_BUFFERED_SIZE_FOR_RESET_MARK);
+		}
+		StringBuffer stringbuffer = buffer;
+		encodedDocument.set(stringbuffer.toString());
+
+	}
+
+	protected void setDocumentContentsFromReader(IEncodedDocument structuredDocument, Reader reader) throws IOException {
+
+		StringBuffer allText = readInputStream(reader);
+		structuredDocument.set(allText.toString());
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/DocumentReader.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/DocumentReader.java
new file mode 100644
index 0000000..ae28004
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/DocumentReader.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.document;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * A java.io.Reader that can operate off of an IDocument.
+ */
+public class DocumentReader extends Reader {
+	private IDocument fDocument = null;
+	private int mark = 0;
+	private int position = 0;
+
+	public DocumentReader() {
+		super();
+	}
+
+	public DocumentReader(IDocument document) {
+		this(document, 0);
+	}
+
+	public DocumentReader(IDocument document, int initialPosition) {
+		super();
+		fDocument = document;
+		position = initialPosition;
+	}
+
+	public void close() throws IOException {
+		fDocument = null;
+	}
+
+	/**
+	 * @return
+	 */
+	public IDocument getDocument() {
+		return fDocument;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.Reader#mark(int)
+	 */
+	public void mark(int readAheadLimit) throws IOException {
+		mark = position;
+	}
+
+	public boolean markSupported() {
+		return true;
+	}
+
+	public int read(char[] cbuf, int off, int len) throws IOException {
+		if(fDocument == null)
+			return -1;
+		
+		char[] readChars = null;
+		try {
+			if (position >= fDocument.getLength())
+				return -1;
+			// the IDocument is likely using a GapTextStore, so we can't
+			// retrieve a char[] directly
+			if (position + len > fDocument.getLength())
+				readChars = fDocument.get(position, fDocument.getLength() - position).toCharArray();
+			else
+				readChars = fDocument.get(position, len).toCharArray();
+			System.arraycopy(readChars, 0, cbuf, off, readChars.length);
+			//				System.out.println("" + position + ":" + readChars.length + " "
+			// + StringUtils.escape(new String(readChars)));
+			position += readChars.length;
+			return readChars.length;
+		} catch (Exception e) {
+			throw new IOException("Exception while reading from IDocument: " + e); //$NON-NLS-1$
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.Reader#reset()
+	 */
+	public void reset() throws IOException {
+		position = mark;
+	}
+
+	public void reset(IDocument document, int initialPosition) {
+		fDocument = document;
+		position = initialPosition;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.Reader#reset()
+	 */
+	public void reset(int pos) throws IOException {
+		position = pos;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.Reader#skip(long)
+	 */
+	public long skip(long n) throws IOException {
+		if(fDocument == null)
+			return 0;
+
+		long skipped = n;
+		if (position + n > fDocument.getLength()) {
+			skipped = fDocument.getLength() - position;
+			position = fDocument.getLength();
+		} else {
+			position += n;
+		}
+		return skipped;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/IDocumentCharsetDetector.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/IDocumentCharsetDetector.java
new file mode 100644
index 0000000..4ea8b04
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/IDocumentCharsetDetector.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.document;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.sse.core.internal.encoding.IResourceCharsetDetector;
+
+
+
+public interface IDocumentCharsetDetector extends IResourceCharsetDetector {
+	void set(IDocument document);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/IDocumentLoader.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/IDocumentLoader.java
new file mode 100644
index 0000000..b7eff1e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/IDocumentLoader.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.document;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingRule;
+import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument;
+
+
+/**
+ * Provides methods for the creation of an IStructuredDocument correctly
+ * prepared to work with a particular type of content.
+ */
+public interface IDocumentLoader {
+
+	/**
+	 * @return a new IStructuredDocument prepared by this loader
+	 */
+	IEncodedDocument createNewStructuredDocument();
+
+	/**
+	 * This API is like createNewStructuredDocument, except it should populate
+	 * the structuredDocument with the contents of IFile. Also, those
+	 * StructuredDocuments which are sensitive to the input (that is, the
+	 * parser or parser initialization my require the input) should
+	 * additionally initialize the parser, etc., appropriate to the input.
+	 * 
+	 * As always, the appropriate decoding should be used.
+	 */
+	IEncodedDocument createNewStructuredDocument(IFile iFile) throws java.io.IOException, CoreException;
+
+	/**
+	 * This method must return a new instance of IEncodedDocument, that has
+	 * been initialized with appropriate parser. For many loaders, the
+	 * (default) parser used is known for any input. For others, the correct
+	 * parser (and its initialization) is normally dependent on the content of
+	 * the file. This no-argument method should assume "empty input" and would
+	 * therefore return the default parser for the default contentType.
+	 */
+	IEncodedDocument createNewStructuredDocument(String filename, InputStream istream) throws java.io.IOException;
+
+	IEncodedDocument createNewStructuredDocument(String filename, InputStream istream, EncodingRule encodingRule) throws java.io.IOException;
+
+	/**
+	 * @return the document partitioner
+	 */
+	IDocumentPartitioner getDefaultDocumentPartitioner();
+
+	IDocumentCharsetDetector getDocumentEncodingDetector();
+
+	/**
+	 * A utility method, but depends on subclasses to implement the preferred
+	 * end of line for a particular content type. Note: subclasses should not
+	 * re-implement this method (there's no reason to, even though its part of
+	 * interface). This method not only converts end-of-line characters, if
+	 * needed, but sets the correct end-of-line delimiter in
+	 * structuredDocument. The returned value is either the original string,
+	 * if no conversion is needed, or a new string with end-of-lines
+	 * converted.
+	 * 
+	 * @deprecated - the content's line delimiters should be preserved
+	 */
+	StringBuffer handleLineDelimiter(StringBuffer originalString, IEncodedDocument theStructuredDocument);
+
+	void reload(IEncodedDocument document, Reader reader) throws IOException;
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/StructuredDocumentFactory.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/StructuredDocumentFactory.java
new file mode 100644
index 0000000..41618fa
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/StructuredDocumentFactory.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.document;
+
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument;
+import org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument;
+
+
+/**
+ * At the moment, this is primarily intended as a convenience to help switch
+ * between various types of threading models in the document, all in a central
+ * piece of code.
+ */
+public class StructuredDocumentFactory {
+	private static final int WRITE_SYNCHRONIZED = 3;
+	private static final int DEFAULT = WRITE_SYNCHRONIZED;
+	private static final int UNSYNCHRONIZED = 1;
+
+	private static IStructuredDocument getNewStructuredDocumentInstance(int type, RegionParser parser) {
+		IStructuredDocument result = null;
+		switch (type) {
+			case UNSYNCHRONIZED :
+				result = new BasicStructuredDocument(parser);
+				break;
+			case WRITE_SYNCHRONIZED :
+				result = new JobSafeStructuredDocument(parser);
+				break;
+
+			default :
+				throw new IllegalArgumentException("request document type was not known"); //$NON-NLS-1$
+
+		}
+		return result;
+	}
+
+	/**
+	 * Provides the (system default) structured document initialized with the
+	 * parser.
+	 * 
+	 * @param parser
+	 * @return
+	 */
+	public static IStructuredDocument getNewStructuredDocumentInstance(RegionParser parser) {
+		return getNewStructuredDocumentInstance(DEFAULT, parser);
+	}
+
+	/**
+	 * Not intended to be instantiated
+	 * 
+	 */
+	private StructuredDocumentFactory() {
+		super();
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/TextUtilities.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/TextUtilities.java
new file mode 100644
index 0000000..91ec598
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/TextUtilities.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.document;
+
+
+/**
+ * Collection of text functions.
+ * 
+ * @deprecated - marked as deprecated to remind us to phase this out (and/or
+ *             move to "finished" version).
+ */
+public class TextUtilities {
+
+	/**
+	 * @deprecated if possible, its best to use
+	 *             IDocument.getLegalLineDelimiters()
+	 */
+	public final static String[] fgDelimiters = new String[]{"\n", "\r", "\r\n"};//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+
+	/**
+	 * Determines which one of fgDelimiters appears first in the text. If none
+	 * of them the hint is returned.
+	 */
+	public static String determineLineDelimiter(StringBuffer textBuffer, String[] possibles, String hint) {
+		try {
+			// TODO: avoid use of String instance
+			String text = textBuffer.toString();
+			int[] info = indexOf(possibles, text, 0);
+			return possibles[info[1]];
+		} catch (ArrayIndexOutOfBoundsException x) {
+		}
+		return hint;
+	}
+
+	/**
+	 * Returns the position in the string greater than offset of the longest
+	 * matching search string.
+	 */
+	private static int[] indexOf(String[] searchStrings, String text, int offset) {
+
+		int[] result = {-1, -1};
+
+		for (int i = 0; i < searchStrings.length; i++) {
+			int index = text.indexOf(searchStrings[i], offset);
+			if (index >= 0) {
+
+				if (result[0] == -1) {
+					result[0] = index;
+					result[1] = i;
+				} else if (index < result[0]) {
+					result[0] = index;
+					result[1] = i;
+				} else if (index == result[0] && searchStrings[i].length() > searchStrings[result[1]].length()) {
+					result[0] = index;
+					result[1] = i;
+				}
+			}
+		}
+
+		return result;
+
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/filebuffers/BasicStructuredDocumentFactory.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/filebuffers/BasicStructuredDocumentFactory.java
new file mode 100644
index 0000000..16467b6
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/filebuffers/BasicStructuredDocumentFactory.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.filebuffers;
+
+import org.eclipse.core.filebuffers.IDocumentFactory;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.content.IContentTypeManager;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry;
+import org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument;
+
+
+/**
+ * Generic IDocumentFactory for IStructuredDocuments to be used by the
+ * org.eclipse.core.filebuffers.documentCreation extension point. This class
+ * is not meant to be subclassed.
+ * 
+ * @plannedfor 1.0
+ */
+public class BasicStructuredDocumentFactory implements IDocumentFactory, IExecutableExtension {
+
+	/*
+	 * The content type ID used to declare this factory; it is used to find
+	 * the corresponding support for creating the document
+	 */
+	private String fContentTypeIdentifier = null;
+
+	/**
+	 * Constructor, only to be used by the
+	 * org.eclipse.core.filebuffers.documentCreation extension point.
+	 */
+	public BasicStructuredDocumentFactory() {
+		super();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.filebuffers.IDocumentFactory#createDocument()
+	 */
+	public IDocument createDocument() {
+		IDocument document = null;
+		IContentType contentType = Platform.getContentTypeManager().getContentType(getContentTypeIdentifier());
+		IModelHandler handler = null;
+		while (handler == null && !IContentTypeManager.CT_TEXT.equals(contentType.getId())) {
+			handler = ModelHandlerRegistry.getInstance().getHandlerForContentTypeId(contentType.getId());
+			contentType = contentType.getBaseType();
+		}
+		if (handler != null) {
+			document = handler.getDocumentLoader().createNewStructuredDocument();
+		}
+		else {
+			document = new JobSafeStructuredDocument();
+		}
+		return document;
+	}
+
+	private String getContentTypeIdentifier() {
+		return fContentTypeIdentifier;
+	}
+
+	/*
+	 * Loads the content type ID to be used when creating the Structured Document. 
+	 * 
+	 * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement,
+	 *      java.lang.String, java.lang.Object)
+	 */
+	public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+		fContentTypeIdentifier = config.getAttribute("contentTypeId"); //$NON-NLS-1$
+		if (data != null) {
+			if (data instanceof String && data.toString().length() > 0) {
+				fContentTypeIdentifier = (String) data;
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/AbstractStructuredFormatProcessor.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/AbstractStructuredFormatProcessor.java
new file mode 100644
index 0000000..1e8d690
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/AbstractStructuredFormatProcessor.java
@@ -0,0 +1,524 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Møller - initial IDocumentExtension4 support - #102822
+ *     David Carver (Intalio) - bug 300443 - some constants aren't static final
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.format;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.DocumentRewriteSession;
+import org.eclipse.jface.text.DocumentRewriteSessionType;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+
+
+public abstract class AbstractStructuredFormatProcessor implements IStructuredFormatProcessor {
+	protected IStructuredFormatContraints fFormatContraints = null;
+	protected IProgressMonitor fProgressMonitor = null;
+	public boolean refreshFormatPreferences = true; // special flag for JUnit
+	/*
+	 * Max length of text to be formatted to be considered a "small change"
+	 * Used for document rewrite session type.
+	 */
+	private static final int MAX_SMALL_FORMAT_SIZE = 1000;
+
+	protected void ensureClosed(OutputStream outputStream, InputStream inputStream) {
+
+		try {
+			if (inputStream != null) {
+				inputStream.close();
+			}
+		}
+		catch (IOException e) {
+			Logger.logException(e); // hopeless
+		}
+		try {
+			if (outputStream != null) {
+				outputStream.close();
+			}
+		}
+		catch (IOException e) {
+			Logger.logException(e); // hopeless
+		}
+	}
+
+	public String formatContent(String input) throws IOException, CoreException {
+		if (input == null)
+			return input;
+
+		IStructuredModel structuredModel = null;
+		InputStream inputStream = null;
+		try {
+			// setup structuredModel
+			// Note: We are getting model for read. Will return formatted
+			// string and NOT save model.
+			inputStream = new ByteArrayInputStream(input.getBytes("UTF8")); //$NON-NLS-1$
+			String id = inputStream.toString() + "." + getFileExtension(); //$NON-NLS-1$
+			structuredModel = StructuredModelManager.getModelManager().getModelForRead(id, inputStream, null);
+
+			// format
+			formatModel(structuredModel);
+
+			// return output
+			return structuredModel.getStructuredDocument().get();
+		}
+		finally {
+			ensureClosed(null, inputStream);
+			// release from model manager
+			if (structuredModel != null)
+				structuredModel.releaseFromRead();
+		}
+	}
+
+	public String formatContent(String input, int start, int length) throws IOException, CoreException {
+		if (input == null)
+			return input;
+
+		if ((start >= 0) && (length >= 0) && (start + length <= input.length())) {
+			IStructuredModel structuredModel = null;
+			InputStream inputStream = null;
+			try {
+				// setup structuredModel
+				// Note: We are getting model for read. Will return formatted
+				// string and NOT save model.
+				inputStream = new ByteArrayInputStream(input.getBytes("UTF8")); //$NON-NLS-1$
+				String id = inputStream.toString() + "." + getFileExtension(); //$NON-NLS-1$
+				structuredModel = StructuredModelManager.getModelManager().getModelForRead(id, inputStream, null);
+
+				// format
+				formatModel(structuredModel, start, length);
+
+				// return output
+				return structuredModel.getStructuredDocument().get();
+			}
+			finally {
+				ensureClosed(null, inputStream);
+				// release from model manager
+				if (structuredModel != null)
+					structuredModel.releaseFromRead();
+			}
+		}
+		else
+			return input;
+	}
+
+	public void formatDocument(IDocument document) throws IOException, CoreException {
+		if (document == null)
+			return;
+
+		IStructuredModel structuredModel = null;
+		// OutputStream outputStream = null;
+		try {
+			// setup structuredModel
+			// Note: We are getting model for edit. Will save model if model
+			// changed.
+			structuredModel = StructuredModelManager.getModelManager().getExistingModelForEdit(document);
+
+			// format
+			formatModel(structuredModel);
+
+			// save model if needed
+			if (!structuredModel.isSharedForEdit() && structuredModel.isSaveNeeded())
+				structuredModel.save();
+		}
+		finally {
+			// ensureClosed(outputStream, null);
+			// release from model manager
+			if (structuredModel != null)
+				structuredModel.releaseFromEdit();
+		}
+	}
+
+	public void formatDocument(IDocument document, int start, int length) throws IOException, CoreException {
+		if (document == null)
+			return;
+
+		if ((start >= 0) && (length >= 0) && (start + length <= document.getLength())) {
+			IStructuredModel structuredModel = null;
+			// OutputStream outputStream = null;
+			try {
+				// setup structuredModel
+				// Note: We are getting model for edit. Will save model if
+				// model changed.
+				structuredModel = StructuredModelManager.getModelManager().getExistingModelForEdit(document);
+
+				if (structuredModel != null) {
+					// format
+					formatModel(structuredModel, start, length);
+
+					// save model if needed
+					if (!structuredModel.isSharedForEdit() && structuredModel.isSaveNeeded())
+						structuredModel.save();
+				}
+			}
+			finally {
+				// ensureClosed(outputStream, null);
+				// release from model manager
+				if (structuredModel != null)
+					structuredModel.releaseFromEdit();
+			}
+		}
+	}
+
+	public void formatFile(IFile file) throws IOException, CoreException {
+		if (file == null)
+			return;
+
+		IStructuredModel structuredModel = null;
+		// OutputStream outputStream = null;
+		try {
+			// setup structuredModel
+			// Note: We are getting model for edit. Will save model if model
+			// changed.
+			structuredModel = StructuredModelManager.getModelManager().getModelForEdit(file);
+
+			// format
+			formatModel(structuredModel);
+
+			// save model if needed
+			if (!structuredModel.isSharedForEdit() && structuredModel.isSaveNeeded())
+				structuredModel.save();
+		}
+		finally {
+			// ensureClosed(outputStream, null);
+			// release from model manager
+			if (structuredModel != null) {
+				structuredModel.releaseFromEdit();
+			}
+
+		}
+	}
+
+	public void formatFile(IFile file, int start, int length) throws IOException, CoreException {
+		if (file == null)
+			return;
+
+		IStructuredModel structuredModel = null;
+		// OutputStream outputStream = null;
+		try {
+			// setup structuredModel
+			// Note: We are getting model for edit. Will save model if model
+			// changed.
+			structuredModel = StructuredModelManager.getModelManager().getModelForEdit(file);
+
+			// format
+			formatModel(structuredModel, start, length);
+
+			// save model if needed
+			if (!structuredModel.isSharedForEdit() && structuredModel.isSaveNeeded())
+				structuredModel.save();
+		}
+		finally {
+			// ensureClosed(outputStream, null);
+			// release from model manager
+			if (structuredModel != null)
+				structuredModel.releaseFromEdit();
+		}
+	}
+
+	public void formatFileName(String fileName) throws IOException, CoreException {
+		if (fileName == null)
+			return;
+
+		IStructuredModel structuredModel = null;
+		InputStream inputStream = null;
+		// OutputStream outputStream = null;
+		try {
+			// setup structuredModel
+			// Note: We are getting model for edit. Will save model if model
+			// changed.
+			inputStream = new FileInputStream(fileName);
+			structuredModel = StructuredModelManager.getModelManager().getModelForEdit(fileName, inputStream, null);
+
+			// format
+			formatModel(structuredModel);
+
+			// save model if needed
+			if (!structuredModel.isSharedForEdit() && structuredModel.isSaveNeeded())
+				structuredModel.save();
+		}
+		finally {
+			// ensureClosed(outputStream, inputStream);
+			// release from model manager
+			if (structuredModel != null)
+				structuredModel.releaseFromEdit();
+		}
+	}
+
+	public void formatFileName(String fileName, int start, int length) throws IOException, CoreException {
+		if (fileName == null)
+			return;
+
+		IStructuredModel structuredModel = null;
+		InputStream inputStream = null;
+		// OutputStream outputStream = null;
+		try {
+			// setup structuredModel
+			// Note: We are getting model for edit. Will save model if model
+			// changed.
+			inputStream = new FileInputStream(fileName);
+			structuredModel = StructuredModelManager.getModelManager().getModelForEdit(fileName, inputStream, null);
+
+			// format
+			formatModel(structuredModel, start, length);
+
+			// save model if needed
+			if (!structuredModel.isSharedForEdit() && structuredModel.isSaveNeeded())
+				structuredModel.save();
+		}
+		finally {
+			// ensureClosed(outputStream, inputStream);
+			// release from model manager
+			if (structuredModel != null)
+				structuredModel.releaseFromEdit();
+		}
+	}
+
+	public void formatModel(IStructuredModel structuredModel) {
+		int start = 0;
+		int length = structuredModel.getStructuredDocument().getLength();
+
+		formatModel(structuredModel, start, length);
+	}
+
+	public void formatModel(IStructuredModel structuredModel, int start, int length) {
+		if (structuredModel != null) {
+			// for debugging purposes
+			long startTime = System.currentTimeMillis();
+
+			IDocumentExtension4 docExt4 = null;
+			if (structuredModel.getStructuredDocument() instanceof IDocumentExtension4) {
+				docExt4 = (IDocumentExtension4) structuredModel.getStructuredDocument();
+			}
+			DocumentRewriteSession rewriteSession = null;
+
+			try {
+				// whenever formatting model, fire abouttochange/modelchanged
+				structuredModel.aboutToChangeModel();
+				DocumentRewriteSessionType rewriteType = (length > MAX_SMALL_FORMAT_SIZE) ? DocumentRewriteSessionType.UNRESTRICTED : DocumentRewriteSessionType.UNRESTRICTED_SMALL;
+				rewriteSession = (docExt4 == null || docExt4.getActiveRewriteSession() != null) ? null : docExt4.startRewriteSession(rewriteType);
+
+				if ((start == 0) && (length == structuredModel.getStructuredDocument().getLength()))
+					setFormatWithSiblingIndent(structuredModel, false);
+				else
+					setFormatWithSiblingIndent(structuredModel, true);
+
+				if ((start >= 0) && (length >= 0) && (start + length <= structuredModel.getStructuredDocument().getLength())) {
+					List activeNodes = getAllActiveNodes(structuredModel, start, length);
+					if (activeNodes.size() > 0) {
+						Node firstNode = (Node) activeNodes.get(0);
+						Node lastNode = (Node) activeNodes.get(activeNodes.size() - 1);
+
+						boolean done = false;
+						Node eachNode = firstNode;
+						Node nextNode = null;
+						while (!done) {
+							// update "done"
+							done = (eachNode == lastNode);
+
+							/*
+							 * get next sibling before format because eachNode
+							 * may be deleted, for example when it's an empty
+							 * text node
+							 */
+							nextNode = eachNode.getNextSibling();
+
+							// format each node
+							formatNode(eachNode);
+
+							// update each node
+							if ((nextNode != null) && (nextNode.getParentNode() == null))
+								// nextNode is deleted during format
+								eachNode = eachNode.getNextSibling();
+							else
+								eachNode = nextNode;
+
+							// This should not be needed, but just in case
+							// something went wrong with with eachNode.
+							// We don't want an infinite loop here.
+							if (eachNode == null)
+								done = true;
+						}
+
+					}
+				}
+			}
+			finally {
+				// we need two finally's, just in case first fails
+				try {
+					if ((docExt4 != null) && (rewriteSession != null))
+						docExt4.stopRewriteSession(rewriteSession);
+				}
+				finally {
+					// always make sure to fire changedmodel when done
+					structuredModel.changedModel();
+				}
+			}
+
+			if (Logger.DEBUG_FORMAT) {
+				long endTime = System.currentTimeMillis();
+				System.out.println("formatModel time: " + (endTime - startTime)); //$NON-NLS-1$
+			}
+		}
+	}
+
+	public void formatNode(Node node) {
+		if (node != null) {
+			Node newNode = node;
+
+			// format the owner node if it's an attribute node
+			if (node.getNodeType() == Node.ATTRIBUTE_NODE)
+				newNode = ((Attr) node).getOwnerElement();
+
+			// refresh format preferences before getting formatter
+			if (refreshFormatPreferences)
+				refreshFormatPreferences();
+
+			// get formatter and format contraints
+			IStructuredFormatter formatter = getFormatter(newNode);
+			// TODO_future: added assert to replace "redundant null check".
+			// if formatter is ever null, we should provide some
+			// default formatter to serve as place holder.
+			Assert.isNotNull(formatter, "formatter was null for a node, "); //$NON-NLS-1$
+			IStructuredFormatContraints formatContraints = formatter.getFormatContraints();
+			formatContraints.setFormatWithSiblingIndent(true);
+			// format each node
+			formatter.format(newNode, formatContraints);
+		}
+	}
+
+	/**
+	 * @deprecated Use getAllActiveNodes instead
+	 */
+	protected Vector getActiveNodes(IStructuredModel structuredModel, int startNodeOffset, int length) {
+		List allActiveNodes = getAllActiveNodes(structuredModel, startNodeOffset, length);
+		return new Vector(allActiveNodes);
+	}
+
+	protected List getAllActiveNodes(IStructuredModel structuredModel, int startNodeOffset, int length) {
+		List activeNodes = new ArrayList();
+
+		if (structuredModel != null) {
+			Node startNode = (Node) structuredModel.getIndexedRegion(startNodeOffset);
+			// see https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=4711
+			//
+			// We have to watch for selection boundary conditions. Use this as
+			// an example: <a>text</a><b>text</b>,
+			// If the whole <a> node is selected, like:
+			// |<a>text</a>|<b>text</b>, we need to substract the length by 1
+			// to find
+			// the node at the end of the selection:
+			// structuredModel.getIndexedRegion(startNodeOffset + length - 1),
+			// or else
+			// we'd find the next adjacent node.
+			//
+			// However, when the selection length is 0 (meaning no text is
+			// selected), the cursor is at the beginning
+			// of the node we want to format: |<a>text</a><b>text</b>, the
+			// node at the end of the selection is:
+			// structuredModel.getIndexedRegion(startNodeOffset + length).
+			int endNodeOffset = length > 0 ? startNodeOffset + length - 1 : startNodeOffset + length;
+			Node endNode = (Node) structuredModel.getIndexedRegion(endNodeOffset);
+
+			// make sure it's an non-empty document
+			if (startNode != null) {
+				while (isSiblingOf(startNode, endNode) == false) {
+					if (endNode != null)
+						endNode = endNode.getParentNode();
+					if (endNode == null) {
+						startNode = startNode.getParentNode();
+						// see
+						// https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=4711
+						// and notes above
+						endNodeOffset = length > 0 ? startNodeOffset + length - 1 : startNodeOffset + length;
+						endNode = (Node) structuredModel.getIndexedRegion(endNodeOffset);
+					}
+				}
+
+				while (startNode != endNode) {
+					activeNodes.add(startNode);
+					startNode = startNode.getNextSibling();
+				}
+				if (startNode != null)
+					activeNodes.add(startNode);
+			}
+		}
+
+		return activeNodes;
+	}
+
+	abstract protected String getFileExtension();
+
+	protected IStructuredFormatContraints getFormatContraints(IStructuredModel structuredModel) {
+		// 262135 - NPE during format of empty document
+		if ((fFormatContraints == null) && (structuredModel != null)) {
+			Node node = (Node) structuredModel.getIndexedRegion(0);
+
+			if (node != null) {
+				IStructuredFormatter formatter = getFormatter(node);
+				if (formatter != null) {
+					fFormatContraints = formatter.getFormatContraints();
+				}
+			}
+		}
+
+		return fFormatContraints;
+	}
+
+	abstract protected IStructuredFormatter getFormatter(Node node);
+
+	protected boolean isSiblingOf(Node node, Node endNode) {
+		if (endNode == null)
+			return true;
+		else {
+			Node siblingNode = node;
+			while (siblingNode != null) {
+				if (siblingNode == endNode)
+					return true;
+				else
+					siblingNode = siblingNode.getNextSibling();
+			}
+			return false;
+		}
+	}
+
+	abstract protected void refreshFormatPreferences();
+
+	protected void setFormatWithSiblingIndent(IStructuredModel structuredModel, boolean formatWithSiblingIndent) {
+		// 262135 - NPE during format of empty document
+		IStructuredFormatContraints formatContraints = getFormatContraints(structuredModel);
+
+		if (formatContraints != null)
+			formatContraints.setFormatWithSiblingIndent(formatWithSiblingIndent);
+	}
+
+	public void setProgressMonitor(IProgressMonitor monitor) {
+		fProgressMonitor = monitor;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/IStructuredFormatContraints.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/IStructuredFormatContraints.java
new file mode 100644
index 0000000..2730043
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/IStructuredFormatContraints.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.format;
+
+/**
+ * These are items that change from element to element.
+ * Passed from node to node in a recursive call.
+ * eg. current indent is 2 deep, but for the next node might be 3...
+ */
+public interface IStructuredFormatContraints {
+	boolean getClearAllBlankLines();
+
+	String getCurrentIndent();
+
+	boolean getFormatWithSiblingIndent();
+
+	boolean getInPreserveSpaceElement();
+
+	/** 
+	 * some special elements can ignore clearing blank lines
+	 * */
+	void setClearAllBlankLines(boolean clearAllBlankLines);
+
+	void setCurrentIndent(String currentIndent);
+
+	void setFormatWithSiblingIndent(boolean formatWithSiblingIndent);
+	
+	void setInPreserveSpaceElement(boolean inPreserveSpaceElement);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/IStructuredFormatPreferences.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/IStructuredFormatPreferences.java
new file mode 100644
index 0000000..2cef142
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/IStructuredFormatPreferences.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.format;
+
+/**
+ * These are items that do not change from element to element.
+ * Passed from node to node in a recursive call because sometimes
+ * child nodes don't have access to the preferences
+ */
+public interface IStructuredFormatPreferences {
+	
+	boolean getClearAllBlankLines();
+
+	String getIndent();
+
+	int getLineWidth();
+
+	void setClearAllBlankLines(boolean clearAllBlankLines);
+
+	void setIndent(String indent);
+
+	void setLineWidth(int lineWidth);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/IStructuredFormatProcessor.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/IStructuredFormatProcessor.java
new file mode 100644
index 0000000..b83aac3
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/IStructuredFormatProcessor.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.format;
+
+import java.io.IOException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.w3c.dom.Node;
+
+/**
+ * The main formatting engine.  
+ * Loops through all the nodes in an IStructuredModel.
+ */
+public interface IStructuredFormatProcessor {
+
+	/**
+	 * This form of the FormatProcessor takes an IDocument as input, creates a
+	 * temporary model of content type calculated using the IDocument's file
+	 * extension, formats the model within start and length, then releases the
+	 * model.
+	 */
+	void formatDocument(IDocument document, int start, int length) throws IOException, CoreException;
+
+	/**
+	 * This form of the FormatProcessor takes an IFile as input, creates a
+	 * temporary model of content type calculated using the IFile's file
+	 * extension, formats the whole model, then releases the model.
+	 */
+	void formatFile(IFile file) throws IOException, CoreException;
+
+	/**
+	 * This form of the FormatProcessor takes a model as input, and formats
+	 * the whole model.
+	 */
+	void formatModel(IStructuredModel structuredModel);
+
+	/**
+	 * This form of the FormatProcessor takes a model as input, and formats
+	 * the model within start and length.
+	 */
+	void formatModel(IStructuredModel structuredModel, int start, int length);
+
+	/**
+	 * This form of the FormatProcessor takes a node as input, and formats the
+	 * node and all its children.
+	 */
+	void formatNode(Node node);
+
+	/**
+	 * Sets the progress monitor for this <code>IStructuredFormatProcessor</code>.
+	 * The monitor is used to display progress or cancel if the formatter is run 
+	 * in a background job.
+	 * @param monitor
+	 */
+	void setProgressMonitor(IProgressMonitor monitor);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/IStructuredFormatter.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/IStructuredFormatter.java
new file mode 100644
index 0000000..6c23d12
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/IStructuredFormatter.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.format;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.w3c.dom.Node;
+
+/**
+ * Knows how to format a particular node.
+ * 
+ * eg. generic node, text node, document node, comment, etc...
+ */
+public interface IStructuredFormatter {
+	
+	void format(Node node);
+
+	void format(Node node, IStructuredFormatContraints formatContraints);
+
+	IStructuredFormatContraints getFormatContraints();
+
+	IStructuredFormatPreferences getFormatPreferences();
+
+	void setFormatPreferences(IStructuredFormatPreferences formatPreferences);
+
+	void setProgressMonitor(IProgressMonitor monitor);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/StructuredFormatContraints.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/StructuredFormatContraints.java
new file mode 100644
index 0000000..ca47e41
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/StructuredFormatContraints.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Møller - xml:space='preserve' support
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.format;
+
+public class StructuredFormatContraints implements IStructuredFormatContraints {
+	private boolean fClearAllBlankLines;
+	private String fCurrentIndent = ""; //$NON-NLS-1$
+	private boolean fFormatWithSiblingIndent = false;
+	private boolean fInPreserveSpaceElement = false;
+
+	public boolean getClearAllBlankLines() {
+		return fClearAllBlankLines;
+	}
+
+	public String getCurrentIndent() {
+		return fCurrentIndent;
+	}
+
+	public boolean getFormatWithSiblingIndent() {
+		return fFormatWithSiblingIndent;
+	}
+
+	public void setClearAllBlankLines(boolean clearAllBlankLines) {
+		fClearAllBlankLines = clearAllBlankLines;
+	}
+
+	public void setCurrentIndent(String currentIndent) {
+		fCurrentIndent = currentIndent;
+	}
+
+	public void setFormatWithSiblingIndent(boolean formatWithSiblingIndent) {
+		fFormatWithSiblingIndent = formatWithSiblingIndent;
+	}
+
+	public boolean getInPreserveSpaceElement() {
+		return fInPreserveSpaceElement;
+	}
+
+	public void setInPreserveSpaceElement(boolean inPreserveSpaceElement) {
+		fInPreserveSpaceElement = inPreserveSpaceElement;		
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/StructuredFormatPreferences.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/StructuredFormatPreferences.java
new file mode 100644
index 0000000..96f1b92
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/format/StructuredFormatPreferences.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.format;
+
+public class StructuredFormatPreferences implements IStructuredFormatPreferences {
+	private boolean fClearAllBlankLines;
+	private String fIndent;
+	private int fLineWidth;
+
+	public boolean getClearAllBlankLines() {
+		return fClearAllBlankLines;
+	}
+
+	public String getIndent() {
+		return fIndent;
+	}
+
+	public int getLineWidth() {
+		return fLineWidth;
+	}
+
+	public void setClearAllBlankLines(boolean clearAllBlankLines) {
+		fClearAllBlankLines = clearAllBlankLines;
+	}
+
+	public void setIndent(String indent) {
+		fIndent = indent;
+	}
+
+	public void setLineWidth(int lineWidth) {
+		fLineWidth = lineWidth;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/modelhandler/AbstractModelHandler.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/modelhandler/AbstractModelHandler.java
new file mode 100644
index 0000000..6c45577
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/modelhandler/AbstractModelHandler.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.modelhandler;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.internal.modelhandler.PluginContributedFactoryReader;
+
+/**
+ * ISSUE: need to provide this functionality in improved API.
+ */
+
+public abstract class AbstractModelHandler implements IModelHandler {
+	private String associatedContentTypeId;
+	private boolean defaultSetting;
+	private String modelHandlerID;
+
+	public AbstractModelHandler() {
+		super();
+	}
+
+	/**
+	 * These factories are added automatically by model manager
+	 */
+	public List getAdapterFactories() {
+		List result = new ArrayList();
+		Collection holdFactories = PluginContributedFactoryReader.getInstance().getFactories(this);
+		if (holdFactories != null) {
+			result.addAll(holdFactories);
+		}
+		return result;
+	}
+
+	public String getAssociatedContentTypeId() {
+		return associatedContentTypeId;
+	}
+
+	public abstract IDocumentCharsetDetector getEncodingDetector();
+
+	public String getId() {
+		return modelHandlerID;
+	}
+
+	public boolean isDefault() {
+		return defaultSetting;
+	}
+
+	protected void setAssociatedContentTypeId(String contentTypeId) {
+		associatedContentTypeId = contentTypeId;
+	}
+
+	public void setDefault(boolean defaultParam) {
+		defaultSetting = defaultParam;
+	}
+
+	protected void setId(String id) {
+		modelHandlerID = id;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/modelhandler/EmbeddedTypeHandler.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/modelhandler/EmbeddedTypeHandler.java
new file mode 100644
index 0000000..b551190
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/modelhandler/EmbeddedTypeHandler.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.modelhandler;
+
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.model.FactoryRegistry;
+
+
+/**
+ */
+public interface EmbeddedTypeHandler {
+
+	/**
+	 * These AdapterFactories are NOT added to IStructuredModel's
+	 * IAdapterFactory Registry, but instead expected to be consulted as
+	 * needed by functionality aware of embedded content types.  Additions
+	 * to the model's own factory registry should be done in
+	 * {@link #initializeFactoryRegistry(FactoryRegistry)}
+	 */
+	List getAdapterFactories();
+
+	/**
+	 * Returns the unique identifier for the content type family this
+	 * ContentTypeDescription belongs to.
+	 */
+	String getFamilyId();
+
+	/**
+	 * Returns a list of mime types (as Strings) this handler is appropriate
+	 * for
+	 */
+	List getSupportedMimeTypes();
+	
+	/**
+	 * If this hander can handle a given mimeType.
+	 * 
+	 * This is a looser check than simply checking if a give mimeType
+	 * in the list of supported types, so it should be used with that
+	 * in mind.  That is, the supported mimeType list should ideally be
+	 * checked first.
+	 * 
+	 * eg. if a mime type ends with "+xml", like voice+xml
+	 *     the EmbeddedXML handler should be able to handle it
+	 *     
+	 * @return true if this handler thinks can handle the given mimeType
+	 */
+	boolean canHandleMimeType(String mimeType);
+
+	/**
+	 * This method is to give the EmbeddedContentType an opportunity to add
+	 * factories directly to the IStructuredModel's IAdapterFactory registry. 
+	 */
+	void initializeFactoryRegistry(FactoryRegistry registry);
+
+	/**
+	 * initializeParser, for example, setting up a "block" tags list using an
+	 * extended interface
+	 */
+	void initializeParser(RegionParser parser);
+
+	boolean isDefault();
+
+	EmbeddedTypeHandler newInstance();
+
+	void uninitializeFactoryRegistry(FactoryRegistry registry);
+
+	void uninitializeParser(RegionParser parser);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/modelhandler/IDocumentTypeHandler.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/modelhandler/IDocumentTypeHandler.java
new file mode 100644
index 0000000..aa62963
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/modelhandler/IDocumentTypeHandler.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.modelhandler;
+
+import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+
+/**
+ * Responsible for providing the mechanisms used in the correct loading of an
+ * IStructuredDocument's contents and determine its self-described encoding.
+ */
+public interface IDocumentTypeHandler {
+
+	/**
+	 * The Loader is reponsible for decoding the Resource,
+	 */
+	IDocumentLoader getDocumentLoader();
+
+	/**
+	 * @deprecated - likely to go away, so I marked as deprecated to
+	 *             discoursage use
+	 */
+	IDocumentCharsetDetector getEncodingDetector();
+
+	/**
+	 * Must return unique ID that is the same as identified in plugin registry
+	 */
+	String getId();
+
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/modelhandler/IModelHandler.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/modelhandler/IModelHandler.java
new file mode 100644
index 0000000..588f39e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/modelhandler/IModelHandler.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.modelhandler;
+
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+
+
+/**
+ * Responsible for providing the mechanisms used in the correct loading of an
+ * IStructuredModel's contents and initialization of its adapter factories.
+ */
+public interface IModelHandler extends IDocumentTypeHandler {
+	/**
+	 * This method should return Factories which are added automatically by
+	 * IModelManager. This can and will often be an empty List (or null),
+	 * since some AdapterFactories must be added by Loader directly, and most
+	 * should be added by Editors. FormatAdapterFactory is an example of one
+	 * that can be returned here, since the timing of adding it is not
+	 * critical, but it may be needed even when an editor is not being used.
+	 */
+	List getAdapterFactories();
+
+	/**
+	 * Returns the ID for the associated ContentTypeHandler But is needed for
+	 * now.
+	 */
+	String getAssociatedContentTypeId();
+
+	/**
+	 * The Loader is reponsible for decoding the Resource,
+	 */
+	IModelLoader getModelLoader();
+
+	boolean isDefault();
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/BlockMarker.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/BlockMarker.java
new file mode 100644
index 0000000..468b360
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/BlockMarker.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.parser;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+
+
+/**
+ * ISSUE: need to provide functionality in improved API. 
+ */
+public class BlockMarker extends TagMarker {
+
+	// allow for JSP expressions within the block
+	protected boolean fAllowJSP = true;
+
+	protected boolean fCaseSensitive = false;
+
+	// the context for the contents of this tag (BLOCK_TEXT, JSP_CONTENT,
+	// etc.)
+	protected String fContext;
+
+	public BlockMarker(String tagName, ITextRegion marker, String context) {
+		this(tagName, marker, context, true);
+	}
+
+	public BlockMarker(String tagName, ITextRegion marker, String context, boolean caseSensitive) {
+		this(tagName, marker, context, caseSensitive, true);
+	}
+
+	public BlockMarker(String tagName, ITextRegion marker, String context, boolean caseSensitive, boolean allowJSP) {
+		super(tagName, marker);
+		setContext(context);
+		setCaseSensitive(caseSensitive);
+		setAllowJSP(allowJSP);
+	}
+
+	public BlockMarker(String tagName, String regionContext, boolean caseSensitive) {
+		this(tagName, null, regionContext, caseSensitive, false);
+	}
+
+	/**
+	 * Gets the allowJSP.
+	 * 
+	 * @return Returns a boolean
+	 */
+	public boolean allowsJSP() {
+		return fAllowJSP;
+	}
+
+	/**
+	 * Gets the context.
+	 * 
+	 * @return Returns a String
+	 */
+	public String getContext() {
+		return fContext;
+	}
+
+	/**
+	 * 
+	 * @return boolean
+	 */
+	public final boolean isCaseSensitive() {
+		return fCaseSensitive;
+	}
+
+	/**
+	 * Sets the allowJSP.
+	 * 
+	 * @param allowJSP
+	 *            The allowJSP to set
+	 */
+	public void setAllowJSP(boolean allowJSP) {
+		fAllowJSP = allowJSP;
+	}
+
+	public final void setCaseSensitive(boolean sensitive) {
+		fCaseSensitive = sensitive;
+	}
+
+	/**
+	 * Sets the context.
+	 * 
+	 * @param context
+	 *            The context to set
+	 */
+	public void setContext(String context) {
+		fContext = context;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/BlockTagParser.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/BlockTagParser.java
new file mode 100644
index 0000000..6bd6b70
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/BlockTagParser.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.parser;
+
+
+
+import java.util.List;
+
+public interface BlockTagParser {
+
+	void addBlockMarker(BlockMarker marker);
+
+	void beginBlockScan(String tagName);
+
+	BlockMarker getBlockMarker(String tagName);
+
+	List getBlockMarkers();
+
+	void removeBlockMarker(BlockMarker marker);
+
+	void removeBlockMarker(String tagName);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/BlockTokenizer.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/BlockTokenizer.java
new file mode 100644
index 0000000..b5ad534
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/BlockTokenizer.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.parser;
+
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+
+
+public interface BlockTokenizer {
+
+	void addBlockMarker(BlockMarker marker);
+
+	void beginBlockMarkerScan(String newTagName, String context);
+
+	void beginBlockTagScan(String newTagName);
+
+	List getBlockMarkers();
+
+	ITextRegion getNextToken() throws IOException;
+
+	int getOffset();
+
+	boolean isEOF();
+
+	BlockTokenizer newInstance();
+
+	void removeBlockMarker(BlockMarker marker);
+
+	void removeBlockMarker(String tagname);
+
+	void reset(char[] charArray);
+
+	void reset(char[] charArray, int newOffset);
+
+	void reset(InputStream in);
+
+	void reset(InputStream in, int newOffset);
+
+	void reset(Reader in);
+
+	void reset(Reader in, int newOffset);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/IBlockedStructuredDocumentRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/IBlockedStructuredDocumentRegion.java
new file mode 100644
index 0000000..30eab0c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/IBlockedStructuredDocumentRegion.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.parser;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+
+/**
+ * IBlockedStructuredDocumentRegion is just like an IStructuredDocumentRegion
+ * except results from parsing a "block tag" (such as SCRIPT or STYLE).
+ * Because these are "variable" partition types, its often handy (efficient)
+ * to keep track of the partition type.
+ * 
+ * @plannedfor 1.0
+ */
+public interface IBlockedStructuredDocumentRegion extends IStructuredDocumentRegion {
+	/**
+	 * Return the partion type for this region.
+	 * 
+	 * @return the partion type.
+	 */
+	String getPartitionType();
+
+	/**
+	 * Sets the partion type.
+	 * 
+	 * For use by parsers and re-parsers only.
+	 * 
+	 * @param partitionType
+	 */
+	void setPartitionType(String partitionType);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/JSPCapableParser.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/JSPCapableParser.java
new file mode 100644
index 0000000..3d55973
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/JSPCapableParser.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.parser;
+
+import java.util.List;
+
+public interface JSPCapableParser extends RegionParser, BlockTagParser {
+	void addNestablePrefix(TagMarker marker);
+
+	/**
+	 * returns the TagMarkers for prefixes that are allowed to be nestable
+	 * 
+	 * @return
+	 */
+	List getNestablePrefixes();
+
+	void removeNestablePrefix(String tagName);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/RegionParser.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/RegionParser.java
new file mode 100644
index 0000000..628dfc6
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/RegionParser.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.parser;
+
+
+
+import java.io.Reader;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+
+
+public interface RegionParser {
+
+	IStructuredDocumentRegion getDocumentRegions();
+
+	List getRegions();
+
+	/**
+	 * The 'newInstance' method is similar to 'clone', but does not include
+	 * the copying of any content. For a pure RegionParser itself, there would
+	 * be little state to "clone", but for some subtypes, such as
+	 * StructuredDocumentRegionParser and JSPCapableParser, there could the
+	 * more internal data to "clone", such as the internal tokenizer should be
+	 * cloned (including block tags, etc).
+	 */
+	RegionParser newInstance();
+
+	void reset(Reader reader);
+
+	/**
+	 * An additional offset for use with any position-dependant parsing rules
+	 */
+	void reset(Reader reader, int offset);
+
+	void reset(String input);
+
+	/**
+	 * An additional offset for use with any position-dependant parsing rules
+	 */
+	void reset(String input, int offset);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/StructuredDocumentRegionHandler.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/StructuredDocumentRegionHandler.java
new file mode 100644
index 0000000..31e5cba
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/StructuredDocumentRegionHandler.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.parser;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+
+public interface StructuredDocumentRegionHandler {
+
+	// Sent when a IStructuredDocumentRegion is first parsed
+	public void nodeParsed(IStructuredDocumentRegion aCoreStructuredDocumentRegion);
+
+	// Sent when the calling parser's model undergoes a full reset
+	//   and any information based upon the old model should be
+	//   cleared
+	public void resetNodes();
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/StructuredDocumentRegionHandlerExtension.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/StructuredDocumentRegionHandlerExtension.java
new file mode 100644
index 0000000..85f2d7b
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/StructuredDocumentRegionHandlerExtension.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.parser;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+
+public interface StructuredDocumentRegionHandlerExtension extends StructuredDocumentRegionHandler {
+	void setStructuredDocument(IStructuredDocument newDocument);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/StructuredDocumentRegionParser.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/StructuredDocumentRegionParser.java
new file mode 100644
index 0000000..d4bbe5d
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/StructuredDocumentRegionParser.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.parser;
+
+
+
+public interface StructuredDocumentRegionParser extends RegionParser {
+
+	void addStructuredDocumentRegionHandler(StructuredDocumentRegionHandler handler);
+
+	void removeStructuredDocumentRegionHandler(StructuredDocumentRegionHandler handler);
+
+	void resetHandlers();
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/StructuredDocumentRegionParserExtension.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/StructuredDocumentRegionParserExtension.java
new file mode 100644
index 0000000..474950e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/StructuredDocumentRegionParserExtension.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.parser;
+
+import java.util.List;
+
+
+
+public interface StructuredDocumentRegionParserExtension extends StructuredDocumentRegionParser {
+	/**
+	 * Returns the current list of StructuredDocumentRegionHandlers listening
+	 * to this parser.
+	 * 
+	 * @return List - the list of listeners, the list may not be null and each
+	 *         element in it must implement StructuredDocumentRegionHandler
+	 */
+	List getStructuredDocumentRegionHandlers();
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/TagMarker.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/TagMarker.java
new file mode 100644
index 0000000..3de225d
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/ltk/parser/TagMarker.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.ltk.parser;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+
+/**
+ * ISSUE: need to provide functionality in improved API. 
+ */
+
+public class TagMarker {
+
+	// a ITextRegion (meant to be updated with the model) marking the position
+	// where this tagname becomes effective
+	protected ITextRegion fMarker = null;
+
+	// the tagname
+	protected String fTagName = null;
+
+	/**
+	 *  
+	 */
+	public TagMarker() {
+		super();
+	}
+
+	public TagMarker(String tagname) {
+		super();
+		setTagName(tagname);
+	}
+
+	public TagMarker(String tagname, ITextRegion marker) {
+		super();
+		setTagName(tagname);
+		setMarker(marker);
+	}
+
+	public final ITextRegion getMarker() {
+		return fMarker;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public final String getTagName() {
+		return fTagName;
+	}
+
+	/**
+	 * @return boolean
+	 */
+	public boolean isGlobal() {
+		return fMarker == null;
+	}
+
+	/**
+	 * @param newMarker
+	 */
+	public final void setMarker(ITextRegion newMarker) {
+		fMarker = newMarker;
+	}
+
+	/**
+	 * @param newTagname
+	 *            java.lang.String
+	 */
+	public final void setTagName(String newTagName) {
+		fTagName = newTagName;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/AbstractModelLoader.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/AbstractModelLoader.java
new file mode 100644
index 0000000..caafaaf
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/AbstractModelLoader.java
@@ -0,0 +1,545 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.model;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingRule;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockTagParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionHandler;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionHandlerExtension;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionParser;
+import org.eclipse.wst.sse.core.internal.ltk.parser.StructuredDocumentRegionParserExtension;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredPartitioning;
+import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument;
+import org.eclipse.wst.sse.core.internal.text.rules.StructuredTextPartitioner;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+
+
+/**
+ * This class reads a file and creates an Structured Model.
+ */
+public abstract class AbstractModelLoader implements IModelLoader {
+	protected static final int encodingNameSearchLimit = 1000;
+
+	private static long computeMem() {
+		for (int i = 0; i < 5; i++) {
+			System.gc();
+			System.runFinalization();
+		}
+		return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
+	}
+
+	private boolean DEBUG = false;
+	protected IDocumentLoader documentLoaderInstance;
+
+	/**
+	 * AbstractLoader constructor also initializes encoding converter/mapper
+	 */
+	public AbstractModelLoader() {
+		super();
+	}
+
+	protected void addFactories(IStructuredModel model, List factoryList) {
+		Assert.isNotNull(model);
+		FactoryRegistry registry = model.getFactoryRegistry();
+		Assert.isNotNull(registry, "IStructuredModel " + model.getId() + " has a null FactoryRegistry"); //$NON-NLS-1$ //$NON-NLS-2$
+		if (factoryList != null) {
+			Iterator iterator = factoryList.iterator();
+			while (iterator.hasNext()) {
+				INodeAdapterFactory factory = (INodeAdapterFactory) iterator.next();
+				registry.addFactory(factory);
+			}
+		}
+	}
+
+	/**
+	 * This method should perform all the model initialization required before
+	 * it contains content, namely, it should call newModel, the
+	 * createNewStructuredDocument(), then add those adapter factories which
+	 * must be set before content is applied. This method should be called by
+	 * "load" method. (this is tentative API)
+	 */
+	public IStructuredModel createModel() {
+		documentLoaderInstance = null;
+		IStructuredModel model = newModel();
+		IEncodedDocument structuredDocument = getDocumentLoader().createNewStructuredDocument();
+		if (structuredDocument instanceof IStructuredDocument) {
+			model.setStructuredDocument((IStructuredDocument) structuredDocument);
+			addFactories(model, getAdapterFactories());
+			//
+			initEmbeddedTypePre(model, (IStructuredDocument) structuredDocument);
+			initEmbeddedTypePost(model);
+			// For types with propagating adapters, its important
+			// that the propagating adapter be in place before the contents
+			// are set.
+			preLoadAdapt(model);
+		}
+		return model;
+	}
+
+	public IStructuredModel createModel(IStructuredDocument structuredDocument, String baseLocation, IModelHandler handler) {
+		documentLoaderInstance = null;
+		IStructuredModel model = newModel();
+		model.setBaseLocation(baseLocation);
+		
+		// handler must be set early, incase a re-init is 
+		// required during creation.
+		model.setModelHandler(handler);
+		
+		addFactories(model, getAdapterFactories());
+		// For types with propagating adapters, it's important
+		// that the propagating adapter be in place before the contents
+		// are set.
+		preLoadAdapt(model);
+		initEmbeddedTypePre(model, structuredDocument);
+
+		model.setStructuredDocument(structuredDocument);
+		//
+		initEmbeddedTypePost(model);
+
+		return model;
+	}
+
+	/**
+	 * This method is used for cloning models.
+	 */
+	public IStructuredModel createModel(IStructuredModel oldModel) {
+		documentLoaderInstance = null;
+		IStructuredModel newModel = newModel();
+		IStructuredDocument oldStructuredDocument = oldModel.getStructuredDocument();
+		IStructuredDocument newStructuredDocument = oldStructuredDocument.newInstance();
+		newModel.setStructuredDocument(newStructuredDocument);
+		// NOTE: we DO NOT simply add the standard ones to the new model
+		// addFactories(newModel, getAdapterFactories());
+		// Now, we take the opportunity to add Factories from the oldModel's
+		// registry to the new model's registry .. if they do not already
+		// exist there.
+		duplicateFactoryRegistry(newModel, oldModel);
+		if (newModel instanceof AbstractStructuredModel) {
+			((AbstractStructuredModel) newModel).setContentTypeIdentifier(oldModel.getContentTypeIdentifier());
+		}
+		// addFactories(newModel, oldModel);
+		initEmbeddedType(oldModel, newModel);
+		// For types with propagating adapters, its important
+		// that the propagating adapter be in place before the contents
+		// are set.
+		preLoadAdapt(newModel);
+		return newModel;
+	}
+
+	private void duplicateFactoryRegistry(IStructuredModel newModel, IStructuredModel oldModel) {
+		List oldAdapterFactories = oldModel.getFactoryRegistry().getFactories();
+		List newAdapterFactories = new ArrayList();
+		Iterator oldListIterator = oldAdapterFactories.iterator();
+		while (oldListIterator.hasNext()) {
+			INodeAdapterFactory oldAdapterFactory = (INodeAdapterFactory) oldListIterator.next();
+			// now "clone" the adapterfactory
+			newAdapterFactories.add(oldAdapterFactory.copy());
+		}
+		// now that we have the "cloned" list, add to new model
+		addFactories(newModel, newAdapterFactories);
+	}
+
+	/**
+	 * This method must return those factories which must be attached to the
+	 * structuredModel before content is applied.
+	 */
+	public List getAdapterFactories() {
+		// abstract method returns none
+		return new ArrayList(0);
+	}
+
+	abstract public IDocumentLoader getDocumentLoader();
+
+	/**
+	 * Method initEmbeddedType, "pre"-stage. Nothing to do here in super class.
+	 * 
+	 * @param model
+	 */
+	protected void initEmbeddedTypePre(IStructuredModel model) {
+	}
+
+	/**
+	 * Method initEmbeddedType, "pre"-stage. By default simply calls the
+	 * version of this method that uses only the structured model.
+	 * 
+	 * @param model
+	 *            the model for which to initialize
+	 * @param structuredDocument
+	 *            The structured document containing the text content for the
+	 *            model, which may be a different instance than what is in the
+	 *            model at this stage.
+	 */
+	protected void initEmbeddedTypePre(IStructuredModel model, IStructuredDocument structuredDocument) {
+		initEmbeddedTypePre(model);
+	}
+		
+	protected void initEmbeddedTypePost(IStructuredModel model) {
+	}
+
+	/**
+	 * Method initEmbeddedType. Nothing to do here in super class.
+	 * 
+	 * @param oldModel
+	 * @param newModel
+	 */
+	protected void initEmbeddedType(IStructuredModel oldModel, IStructuredModel newModel) {
+	}
+
+	public void load(IFile file, IStructuredModel model) throws IOException, CoreException {
+		IEncodedDocument structuredDocument = model.getStructuredDocument();
+		if (file == null)
+			structuredDocument = getDocumentLoader().createNewStructuredDocument();
+		else
+			structuredDocument = getDocumentLoader().createNewStructuredDocument(file);
+
+		// TODO: need to straighten out IEncodedDocument mess
+		if (structuredDocument instanceof IStructuredDocument)
+			transformInstance(model.getStructuredDocument(), (IStructuredDocument) structuredDocument);
+		else
+			model.getStructuredDocument().set(structuredDocument.get());
+
+		// original hack
+		// model.setStructuredDocument((IStructuredDocument)
+		// structuredDocument);
+		// ((IStructuredDocument) structuredDocument).fireNewDocument(this);
+		documentLoaderInstance = null;
+		// technicq of future
+		// model.setStructuredDocument((IStructuredDocument)
+		// structuredDocument);
+		// documentLoaderInstance = null;
+	}
+
+	public void load(InputStream inputStream, IStructuredModel model, EncodingRule encodingRule) throws UnsupportedEncodingException, java.io.IOException {
+		// note we don't open the stream, so we don't close it
+		IEncodedDocument structuredDocument = model.getStructuredDocument();
+		if (inputStream == null) {
+			structuredDocument = getDocumentLoader().createNewStructuredDocument();
+		}
+		else {
+			// assume's model has been initialized already with base location
+			structuredDocument = getDocumentLoader().createNewStructuredDocument(model.getBaseLocation(), inputStream, encodingRule);
+			// TODO: model's not designed for this!
+			// we want to move to this "set" method, but the 'fire' was needed
+			// as
+			// a work around for strucutredModel not handling 'set' right, but
+			// that 'fireNewDocument' method was causing unbalance
+			// "aboutToChange" and "changed"
+			// events.
+			// model.setStructuredDocument((IStructuredDocument)
+			// structuredDocument);
+			// ((IStructuredDocument)
+			// structuredDocument).fireNewDocument(this);
+			model.getStructuredDocument().set(structuredDocument.get());
+
+		}
+		documentLoaderInstance = null;
+
+	}
+
+	/**
+	 * deprecated -- use EncodingRule form
+	 */
+	synchronized public void load(InputStream inputStream, IStructuredModel model, String encodingName, String lineDelimiter) throws UnsupportedEncodingException, java.io.IOException {
+		// note we don't open the stream, so we don't close it
+		// TEMP work around to maintain previous function,
+		// until everyone can change to EncodingRule.FORCE_DEFAULT
+		if (encodingName != null && encodingName.trim().length() == 0) {
+			// redirect to new method
+			load(inputStream, model, EncodingRule.FORCE_DEFAULT);
+		}
+		else {
+			load(inputStream, model, EncodingRule.CONTENT_BASED);
+		}
+	}
+
+	public void load(String filename, InputStream inputStream, IStructuredModel model, String junk, String dummy) throws UnsupportedEncodingException, java.io.IOException {
+
+		long memoryUsed = 0;
+		if (DEBUG) {
+			memoryUsed = computeMem();
+			System.out.println("measuring heap memory for " + filename); //$NON-NLS-1$
+			// System.out.println("heap memory used before load: " +
+			// memoryUsed);
+		}
+
+		// during an initial load, we expect the olddocument to be empty
+		// during re-load, however, it would be full.
+		IEncodedDocument newstructuredDocument = null;
+		IEncodedDocument oldStructuredDocument = model.getStructuredDocument();
+
+		// get new document
+		if (inputStream == null) {
+			newstructuredDocument = getDocumentLoader().createNewStructuredDocument();
+		}
+		else {
+			newstructuredDocument = getDocumentLoader().createNewStructuredDocument(filename, inputStream);
+		}
+		if (DEBUG) {
+			long memoryAtEnd = computeMem();
+			// System.out.println("heap memory used after loading new
+			// document: " + memoryAtEnd);
+			System.out.println("    heap memory implied used by document: " + (memoryAtEnd - memoryUsed)); //$NON-NLS-1$
+		}
+
+
+		// TODO: need to straighten out IEncodedDocument mess
+		if (newstructuredDocument instanceof IStructuredDocument) {
+			transformInstance((IStructuredDocument) oldStructuredDocument, (IStructuredDocument) newstructuredDocument);
+		}
+		else {
+			// we don't really expect this case, just included for safety
+			oldStructuredDocument.set(newstructuredDocument.get());
+		}
+		// original hack
+		// model.setStructuredDocument((IStructuredDocument)
+		// structuredDocument);
+		// ((IStructuredDocument) structuredDocument).fireNewDocument(this);
+		documentLoaderInstance = null;
+		// technicq of future
+		// model.setStructuredDocument((IStructuredDocument)
+		// structuredDocument);
+		// documentLoaderInstance = null;
+		if (DEBUG) {
+			long memoryAtEnd = computeMem();
+			// System.out.println("heap memory used after setting to model: "
+			// + memoryAtEnd);
+			System.out.println("    heap memory implied used by document and model: " + (memoryAtEnd - memoryUsed)); //$NON-NLS-1$
+		}
+
+	}
+
+	/**
+	 * required by interface, being declared here abstractly just as another
+	 * reminder.
+	 */
+	abstract public IStructuredModel newModel();
+
+	/**
+	 * There's nothing to do here in abstract class for initializing adapters.
+	 * Subclasses can and should override this method and provide proper
+	 * intialization (For example, to get DOM document and 'getAdapter' on it,
+	 * so that the first node/notifier has the adapter on it.)
+	 */
+	protected void preLoadAdapt(IStructuredModel structuredModel) {
+
+
+	}
+
+	/**
+	 * Normally, here in the abstact class, there's nothing to do, but we will
+	 * reset text, since this MIGHT end up being called to recover from error
+	 * conditions (e.g. IStructuredDocument exceptions) And, can be called by
+	 * subclasses.
+	 */
+	public IStructuredModel reinitialize(IStructuredModel model) {
+		// Note: the "minimumization" routines
+		// of 'replaceText' allow many old nodes to pass through, when
+		// really its assumed they are created anew.
+		// so we need to use 'setText' (I think "setText' ends up
+		// throwing a 'newModel' event though, that may have some
+		// implications.
+		model.getStructuredDocument().setText(this, model.getStructuredDocument().get());
+		return model;
+	}
+
+	/**
+	 * This method gets a fresh copy of the data, and repopulates the models
+	 * ... by a call to setText on the structuredDocument. This method is
+	 * needed in some cases where clients are sharing a model and then changes
+	 * canceled. Say for example, one editor and several "displays" are
+	 * sharing a model, if the editor is closed without saving changes, then
+	 * the displays still need a model, but they should revert to the original
+	 * unsaved version.
+	 */
+	synchronized public void reload(InputStream inputStream, IStructuredModel structuredModel) {
+		documentLoaderInstance = null;
+		try {
+			// temp solution ... we should be able to do better (more
+			// efficient) in future.
+			// Adapters will (probably) need to be sensitive to the fact that
+			// the document instance changed
+			// (by being life cycle listeners)
+			load(inputStream, structuredModel, EncodingRule.CONTENT_BASED);
+
+			// // Note: we apparently read the data (and encoding) correctly
+			// // before, we just need to make sure we followed the same rule
+			// as
+			// // before.
+			// EncodingMemento previousMemento =
+			// structuredModel.getStructuredDocument().getEncodingMemento();
+			// EncodingRule previousRule = previousMemento.getEncodingRule();
+			// //IFile file = ResourceUtil.getFileFor(structuredModel);
+			// // Note: there's opportunity here for some odd behavior, if the
+			// // settings have changed from the first load to the reload.
+			// But,
+			// // hopefully,
+			// // will result in the intended behavior.
+			// Reader allTextReader =
+			// getDocumentLoader().readInputStream(inputStream, previousRule);
+			//
+			// // TODO: avoid use of String instance
+			// getDocumentLoader().reload(structuredModel.getStructuredDocument(),
+			// allTextReader);
+			// // and now "reset" encoding memento to keep it current with the
+			// // one
+			// // that was just determined.
+			// structuredModel.getStructuredDocument().setEncodingMemento(getDocumentLoader().getEncodingMemento());
+			// structuredModel.setDirtyState(false);
+			// StructuredTextUndoManager undoMgr =
+			// structuredModel.getUndoManager();
+			// if (undoMgr != null) {
+			// undoMgr.reset();
+			// }
+		}
+		catch (UnsupportedEncodingException e) {
+			// couldn't happen. The program has apparently
+			// read the model once, and there'd be no reason the encoding
+			// could not be used again.
+			Logger.logException("Warning:  XMLLoader::reload.  This exception really should not have happened!! But will attemp to continue after dumping stack trace", e); //$NON-NLS-1$
+			throw new Error("Program Error", e); //$NON-NLS-1$
+		}
+		catch (IOException e) {
+			// couldn't happen. The program has apparently
+			// read the model once, and there'd be no (common) reason it
+			// couldn't be loaded again.
+			Logger.logException("Warning:  XMLLoader::reload.  This exception really should not have happened!! But will attemp to continue after dumping stack trace", e); //$NON-NLS-1$
+			throw new Error("Program Error", e); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * this work is done better elsewhere, but done here for this version to
+	 * reduce changes. especially since the need for it should go away once we
+	 * no longer need to re-use old document instance.
+	 */
+	private void transformInstance(IStructuredDocument oldInstance, IStructuredDocument newInstance) {
+		/**
+		 * https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=4920
+		 * 
+		 * JSP taglib support broken, correct by duplicating extended setup
+		 * information (BlockTagParser extension,
+		 * StructuredDocumentRegionParser extensions)
+		 */
+		RegionParser oldParser = oldInstance.getParser();
+		RegionParser newParser = newInstance.getParser().newInstance();
+		// Register all of the old StructuredDocumentRegionHandlers on the new
+		// parser
+		if (oldParser instanceof StructuredDocumentRegionParserExtension && newParser instanceof StructuredDocumentRegionParserExtension) {
+			List oldHandlers = ((StructuredDocumentRegionParserExtension) oldParser).getStructuredDocumentRegionHandlers();
+			for (int i = 0; i < oldHandlers.size(); i++) {
+				StructuredDocumentRegionHandler handler = ((StructuredDocumentRegionHandler) oldHandlers.get(i));
+				if (handler instanceof StructuredDocumentRegionHandlerExtension) {
+					/**
+					 * Skip the transferring here, the handler will do this
+					 * after everything else but the source is transferred.
+					 */
+				}
+				else {
+					((StructuredDocumentRegionParser) oldParser).removeStructuredDocumentRegionHandler(handler);
+					((StructuredDocumentRegionParser) newParser).addStructuredDocumentRegionHandler(handler);
+					handler.resetNodes();
+				}
+			}
+		}
+		// Add any global BlockMarkers to the new parser
+		if (oldParser instanceof BlockTagParser && newParser instanceof BlockTagParser) {
+			List oldBlockMarkers = ((BlockTagParser) oldParser).getBlockMarkers();
+			for (int i = 0; i < oldBlockMarkers.size(); i++) {
+				BlockMarker blockMarker = ((BlockMarker) oldBlockMarkers.get(i));
+				if (blockMarker.isGlobal()) {
+					((BlockTagParser) newParser).addBlockMarker(blockMarker);
+				}
+			}
+		}
+
+		((BasicStructuredDocument) oldInstance).setParser(newParser);
+
+		((BasicStructuredDocument) oldInstance).setReParser(newInstance.getReParser().newInstance());
+
+		if (newInstance.getDocumentPartitioner() instanceof StructuredTextPartitioner) {
+			StructuredTextPartitioner partitioner = null;
+			if (oldInstance instanceof IDocumentExtension3 && newInstance instanceof IDocumentExtension3) {
+				partitioner = ((StructuredTextPartitioner) ((IDocumentExtension3) newInstance).getDocumentPartitioner(IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING));
+				if (partitioner != null) {
+					partitioner = (StructuredTextPartitioner) partitioner.newInstance();
+				}
+				((IDocumentExtension3) oldInstance).setDocumentPartitioner(IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING, partitioner);
+			}
+			if (partitioner == null) {
+				partitioner = (StructuredTextPartitioner) ((StructuredTextPartitioner) newInstance.getDocumentPartitioner()).newInstance();
+				oldInstance.setDocumentPartitioner(partitioner);
+			}
+			if (partitioner != null) {
+				partitioner.connect(oldInstance);
+			}
+		}
+
+		String existingLineDelimiter = null;
+		try {
+			existingLineDelimiter = newInstance.getLineDelimiter(0);
+		}
+		catch (BadLocationException e) {
+			// if empty file, assume platform default
+			// TODO: should be using user set preference, per content type?
+			existingLineDelimiter = System.getProperty("line.separator"); //$NON-NLS-1$
+		}
+
+		oldInstance.setLineDelimiter(existingLineDelimiter); //$NON-NLS-1$);
+		if (newInstance.getEncodingMemento() != null) {
+			oldInstance.setEncodingMemento((EncodingMemento) newInstance.getEncodingMemento().clone());
+		}
+
+		/**
+		 * https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=4920
+		 * 
+		 * JSP taglib support broken, correct by duplicating extended setup
+		 * information (BlockTagParser extension,
+		 * StructuredDocumentRegionParser extensions)
+		 */
+		if (oldParser instanceof StructuredDocumentRegionParserExtension && newParser instanceof StructuredDocumentRegionParserExtension) {
+			List oldHandlers = ((StructuredDocumentRegionParserExtension) oldParser).getStructuredDocumentRegionHandlers();
+			for (int i = 0; i < oldHandlers.size(); i++) {
+				StructuredDocumentRegionHandler handler = ((StructuredDocumentRegionHandler) oldHandlers.get(i));
+				if (handler instanceof StructuredDocumentRegionHandlerExtension) {
+					StructuredDocumentRegionHandlerExtension handlerExtension = (StructuredDocumentRegionHandlerExtension) handler;
+					handlerExtension.setStructuredDocument(oldInstance);
+				}
+			}
+		}
+		String holdString = newInstance.get();
+		newInstance = null;
+		oldInstance.set(holdString);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/AbstractStructuredModel.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/AbstractStructuredModel.java
new file mode 100644
index 0000000..a5a653d
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/AbstractStructuredModel.java
@@ -0,0 +1,1517 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2011 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.model;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.jobs.ILock;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.SSECoreMessages;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingRule;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.sse.core.internal.provisional.DocumentChanged;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLifecycleListener;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IModelStateListener;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.provisional.events.AboutToBeChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.IModelAboutToBeChangedListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.NewDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceInUse;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager;
+import org.eclipse.wst.sse.core.internal.util.URIResolver;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+
+
+public abstract class AbstractStructuredModel implements IStructuredModel {
+
+	private static final String MODEL_MANAGER_NULL = "Warning: AbstractStructuredModel::close:  model manager was null during a close of a model (which should be impossible)"; //$NON-NLS-1$
+
+	class DirtyStateWatcher implements IStructuredDocumentListener {
+
+		public void newModel(NewDocumentEvent structuredDocumentEvent) {
+
+			// I don't think its safe to assume a new model
+			// is always "fresh", so we'll leave dirty state
+			// unchanged;
+			// but we'll tell everyone about it.
+			setDirtyState(fDirtyState);
+		}
+
+		public void noChange(NoChangeEvent structuredDocumentEvent) {
+
+			// don't change dirty state
+		}
+
+		public void nodesReplaced(StructuredDocumentRegionsReplacedEvent structuredDocumentEvent) {
+
+			setDirtyState(true);
+			// no need to listen any more
+			if (fStructuredDocument != null) {
+				fStructuredDocument.removeDocumentChangedListener(fDirtyStateWatcher);
+			}
+		}
+
+		public void regionChanged(RegionChangedEvent structuredDocumentEvent) {
+
+			setDirtyState(true);
+			// no need to listen any more
+			if (fStructuredDocument != null) {
+				fStructuredDocument.removeDocumentChangedListener(fDirtyStateWatcher);
+			}
+		}
+
+		public void regionsReplaced(RegionsReplacedEvent structuredDocumentEvent) {
+
+			setDirtyState(true);
+			// no need to listen any more
+			if (fStructuredDocument != null) {
+				fStructuredDocument.removeDocumentChangedListener(fDirtyStateWatcher);
+			}
+		}
+	}
+
+	class DocumentToModelNotifier implements IStructuredDocumentListener, IModelAboutToBeChangedListener {
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.events.IModelAboutToBeChangedListener#modelAboutToBeChanged(org.eclipse.wst.sse.core.events.AboutToBeChangedEvent)
+		 */
+		public void modelAboutToBeChanged(AboutToBeChangedEvent structuredDocumentEvent) {
+			// If we didn't originate the change, take note we are about to
+			// change based on our underlying document changing.
+			// If we did originate the change, we, or client, should have
+			// already called aboutToChangeModel.
+			if (structuredDocumentEvent.getOriginalRequester() != this) {
+				aboutToChangeModel();
+			}
+
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#newModel(org.eclipse.wst.sse.core.events.NewDocumentEvent)
+		 */
+		public void newModel(NewDocumentEvent structuredDocumentEvent) {
+			// if we didn't originate the change, take note we have changed
+			if (structuredDocumentEvent.getOriginalRequester() != this) {
+				changedModel();
+			}
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#noChange(org.eclipse.wst.sse.core.events.NoChangeEvent)
+		 */
+		public void noChange(NoChangeEvent structuredDocumentEvent) {
+			// if we didn't originate the change, take note we have changed
+			if (structuredDocumentEvent.getOriginalRequester() != this) {
+				changedModel();
+			}
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#nodesReplaced(org.eclipse.wst.sse.core.events.StructuredDocumentRegionsReplacedEvent)
+		 */
+		public void nodesReplaced(StructuredDocumentRegionsReplacedEvent structuredDocumentEvent) {
+			// if we didn't originate the change, take note we have changed
+			if (structuredDocumentEvent.getOriginalRequester() != this) {
+				changedModel();
+			}
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#regionChanged(org.eclipse.wst.sse.core.events.RegionChangedEvent)
+		 */
+		public void regionChanged(RegionChangedEvent structuredDocumentEvent) {
+			// if we didn't originate the change, take note we have changed
+			if (structuredDocumentEvent.getOriginalRequester() != this) {
+				changedModel();
+			}
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.wst.sse.core.events.IStructuredDocumentListener#regionsReplaced(org.eclipse.wst.sse.core.events.RegionsReplacedEvent)
+		 */
+		public void regionsReplaced(RegionsReplacedEvent structuredDocumentEvent) {
+			// if we didn't originate the change, take note we have changed
+			if (structuredDocumentEvent.getOriginalRequester() != this) {
+				changedModel();
+			}
+		}
+
+	}
+
+	private FactoryRegistry factoryRegistry;
+	private String fBaseLocation;
+	boolean fDirtyState;
+	DirtyStateWatcher fDirtyStateWatcher;
+	DocumentToModelNotifier fDocumentToModelNotifier;
+	private String fExplicitContentTypeIdentifier;
+	private String fId;
+
+	private LifecycleNotificationManager fLifecycleNotificationManager;
+
+	private final Object fListenerLock = new byte[0];
+	protected ILock fLockObject;
+	// private String fLineDelimiter;
+	// private Object fType;
+	private IModelHandler fModelHandler;
+	// issue: we should not "hold on" to model manager, can 
+	// easily get with StructuredModelManager.getModelManager();
+	// but will need to add more null checks.
+	private IModelManager fModelManager;
+	private int fModelStateChanging;
+	private Object[] fModelStateListeners;
+	private boolean fNewState = false;
+	private URIResolver fResolver;
+	protected IStructuredDocument fStructuredDocument;
+	/**
+	 * The time stamp of the underlying resource's modification date, at the
+	 * time this model was created, or the last time it was saved. Note: for
+	 * this version, this variable is not set automatically, be needs to be
+	 * managed by client. The FileModelProvider does this for most cases, but
+	 * if client do not use FileModelProvider, they must set this variable
+	 */
+	public long fSynchronizationStamp = IResource.NULL_STAMP;
+	private boolean reinitializationNeeded;
+	private Object reinitializeStateData;
+
+	/**
+	 * AbstractStructuredModel constructor comment.
+	 */
+	public AbstractStructuredModel() {
+
+		super();
+		fDirtyStateWatcher = new DirtyStateWatcher();
+		fDocumentToModelNotifier = new DocumentToModelNotifier();
+	}
+
+
+	/**
+	 * This method is just for getting an instance of the model manager of the
+	 * right Impl type, to be used "internally" for making protected calls
+	 * directly to the impl class.
+	 */
+	private ModelManagerImpl _getModelManager() {
+		// TODO_future: redesign so we don't need this 'Impl' version
+		if (fModelManager == null) {
+			fModelManager = StructuredModelManager.getModelManager();
+		}
+
+		return (ModelManagerImpl) fModelManager;
+	}
+
+	/**
+	 * This API allows clients to declare that they are about to make a
+	 * "large" change to the model. This change might be in terms of content
+	 * or it might be in terms of the model id or base location. Note that in
+	 * the case of embedded calls, notification to listeners is sent only
+	 * once. Note that the client who is making these changes has the
+	 * responsibility to restore the models state once finished with the
+	 * changes. See getMemento and restoreState. The method
+	 * isModelStateChanging can be used by a client to determine if the model
+	 * is already in a change sequence.
+	 */
+	public void aboutToChangeModel() {
+
+
+		// notice this is just a public avenue to our protected method
+		internalAboutToBeChanged();
+	}
+
+
+	public void aboutToReinitializeModel() {
+
+
+
+		// notice this is just a public avenue to our protected method
+		fireModelAboutToBeReinitialized();
+	}
+
+
+	public void addModelLifecycleListener(IModelLifecycleListener listener) {
+
+		synchronized (fListenerLock) {
+			if (fLifecycleNotificationManager == null) {
+				fLifecycleNotificationManager = new LifecycleNotificationManager();
+			}
+			fLifecycleNotificationManager.addListener(listener);
+		}
+	}
+
+	public void addModelStateListener(IModelStateListener listener) {
+
+		synchronized (fListenerLock) {
+
+			if (!Utilities.contains(fModelStateListeners, listener)) {
+				int oldSize = 0;
+				if (fModelStateListeners != null) {
+					// normally won't be null, but we need to be sure, for
+					// first
+					// time through
+					oldSize = fModelStateListeners.length;
+				}
+				int newSize = oldSize + 1;
+				Object[] newListeners = new Object[newSize];
+				if (fModelStateListeners != null) {
+					System.arraycopy(fModelStateListeners, 0, newListeners, 0, oldSize);
+				}
+				// add listener to last position
+				newListeners[newSize - 1] = listener;
+				//
+				// now switch new for old
+				fModelStateListeners = newListeners;
+			}
+		}
+	}
+
+	/**
+	 * This lock to lock the small bits of data and operations in the models
+	 * themselves. this lock is "shared" with document, so, eventually,
+	 * changes can be made safely from either side.
+	 * 
+	 * @deprecated
+	 */
+	protected final void beginLock() {
+	}
+
+	public void beginRecording(Object requester) {
+
+		beginRecording(requester, null, null);
+	}
+
+	public void beginRecording(Object requester, int cursorPosition, int selectionLength) {
+
+		beginRecording(requester, null, null, cursorPosition, selectionLength);
+	}
+
+	public void beginRecording(Object requester, String label) {
+
+		beginRecording(requester, label, null);
+	}
+
+	public void beginRecording(Object requester, String label, int cursorPosition, int selectionLength) {
+
+		beginRecording(requester, label, null, cursorPosition, selectionLength);
+	}
+
+	public void beginRecording(Object requester, String label, String description) {
+
+		if (getUndoManager() != null)
+			getUndoManager().beginRecording(requester, label, description);
+	}
+
+	public void beginRecording(Object requester, String label, String description, int cursorPosition, int selectionLength) {
+
+		if (getUndoManager() != null)
+			getUndoManager().beginRecording(requester, label, description, cursorPosition, selectionLength);
+	}
+
+	/**
+	 * This API allows a client controlled way of notifying all ModelEvent
+	 * listners that the model has been changed. This method is a matched pair
+	 * to aboutToChangeModel, and *must* be called after aboutToChangeModel
+	 * ... or some listeners could be left waiting indefinitely for the
+	 * changed event. So, its suggested that changedModel always be in a
+	 * finally clause. Likewise, a client should never call changedModel
+	 * without calling aboutToChangeModel first. In the case of embedded
+	 * calls, the notification is just sent once.
+	 */
+	public void changedModel() {
+
+
+		// notice this is just a public avenue to our protected method
+		internalModelChanged();
+		// also note!
+		// if we've been "changed" by a client, we might still need
+		// to be re-initialized, so we'll check and handle that here.
+		// Note only does this provide a solution to some "missed"
+		// re-inits, in provides a built in way for clients to
+		// "force" the model to handle itself, by bracketing any
+		// changes with aboutToChange and changed, the model itself
+		// will check. But only call re-init if all other pending
+		// modelChanged states have been handled.
+		if (fModelStateChanging == 0 && isReinitializationNeeded()) {
+			reinit();
+		}
+	}
+
+
+	/**
+	 * Based on similar method in FileDocumentProvider. It will provide what
+	 * the modificationStamp would be if resetSynchronzationStamp(resource)
+	 * were used, although for this 'compute' API, no changes to the instance
+	 * are made.
+	 */
+	public long computeModificationStamp(IResource resource) {
+
+
+		long modificationStamp = resource.getModificationStamp();
+		IPath path = resource.getLocation();
+		if (path == null) {
+			return modificationStamp;
+		}
+		// Note: checking existence of file is a little different than
+		// impl in
+		// the FileDocumentProvider. See defect number 223790.
+		File file = path.toFile();
+		if (!file.exists()) {
+			return modificationStamp;
+		}
+		modificationStamp = file.lastModified();
+		return modificationStamp;
+	}
+
+
+	/**
+	 * Provides a copy of the model, but a new ID must be provided. The
+	 * principle of this copy is not to copy fields, etc., as is typically
+	 * done in a clone method, but to return a model with the same content in
+	 * the structuredDocument. Note: It is the callers responsibility to
+	 * setBaseLocation, listners, etc., as appropriate. Type and Encoding are
+	 * the only fields set by this method. If the newId provided already exist
+	 * in the model manager, a ResourceInUse exception is thrown.
+	 */
+	public IStructuredModel copy(String newId) throws ResourceInUse {
+
+
+		IStructuredModel newModel = null;
+		// this first one should fail, if not, its treated as an error
+		// If the caller wants to use an existing one, they can call
+		// getExisting
+		// after this failure
+		newModel = getModelManager().getExistingModelForEdit(newId);
+		if (newModel != null) {
+			// be sure to release the reference we got "by accident" (and
+			// no
+			// longer need)
+			newModel.releaseFromEdit();
+			throw new ResourceInUse();
+		}
+		newModel = getModelManager().copyModelForEdit(getId(), newId);
+		return newModel;
+	}
+
+
+	/**
+	 * Disable undo management.
+	 */
+	public void disableUndoManagement() {
+
+		if (getUndoManager() != null)
+			getUndoManager().disableUndoManagement();
+	}
+
+	/**
+	 * Enable undo management.
+	 */
+	public void enableUndoManagement() {
+
+		if (getUndoManager() != null)
+			getUndoManager().enableUndoManagement();
+	}
+
+	/**
+	 * endLock is protected only for a very special purpose. So subclasses can
+	 * call it to end the lock after updates have been made, but before
+	 * notifications are sent
+	 * 
+	 * @deprecated
+	 */
+	protected final void endLock() {
+	}
+
+	public void endRecording(Object requester) {
+
+		if (getUndoManager() != null)
+			getUndoManager().endRecording(requester);
+	}
+
+	public void endRecording(Object requester, int cursorPosition, int selectionLength) {
+
+		if (getUndoManager() != null)
+			getUndoManager().endRecording(requester, cursorPosition, selectionLength);
+	}
+
+	/**
+	 * Informs all registered model state listeners that the the model is
+	 * about to under go a change. This change might be in terms of contents
+	 * or might be in terms of the model's id or base location.
+	 */
+	private void fireModelAboutToBeChanged() {
+
+		// we must assign listeners to local variable, since the add and
+		// remove listner
+		// methods can change the actual instance of the listener array
+		// from another thread
+		if (fModelStateListeners != null) {
+			Object[] holdListeners = fModelStateListeners;
+			for (int i = 0; i < holdListeners.length; i++) {
+				((IModelStateListener) holdListeners[i]).modelAboutToBeChanged(this);
+			}
+		}
+
+	}
+
+	protected void fireModelAboutToBeReinitialized() {
+
+		// we must assign listeners to local variable, since the add and
+		// remove
+		// listner
+		// methods can change the actual instance of the listener array from
+		// another thread
+		if (fModelStateListeners != null) {
+			if (Logger.DEBUG_MODELSTATE) {
+				Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelAboutToBeReinitialized"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			Object[] holdListeners = fModelStateListeners;
+			for (int i = 0; i < holdListeners.length; i++) {
+				// NOTE: trick for transition. We actual use the same
+				// listeners
+				// as modelState, but only send this to those that have
+				// implemented ModelStateExtended.
+				IModelStateListener listener = (IModelStateListener) holdListeners[i];
+				listener.modelAboutToBeReinitialized(this);
+			}
+		}
+	}
+
+	private void fireModelChanged() {
+		// we must assign listeners
+		// to local variable, since the add
+		// and remove listner
+		// methods can change the actual instance of the listener
+		// array from another thread
+		if (fModelStateListeners != null) {
+			Object[] holdListeners = fModelStateListeners;
+			for (int i = 0; i < holdListeners.length; i++) {
+				try {
+					((IModelStateListener) holdListeners[i]).modelChanged(this);
+				}
+				// its so criticial that the begin/end arrive in
+				// pairs,
+				// if there happends to be an error in one of the
+				// modelChanged,
+				// they we want to be sure rest complete ok.
+				catch (Exception e) {
+					Logger.logException(e);
+				}
+			}
+
+		}
+	}
+
+	/**
+	 * Informs all registered model state listeners about a change in the
+	 * dirty state of the model. The dirty state is entirely about changes in
+	 * the content of the model (not, for example, about changes to id, or
+	 * base location -- see modelMoved).
+	 */
+	protected void fireModelDirtyStateChanged(IStructuredModel element, boolean isDirty) {
+
+		// we must assign listeners to local variable, since the add and
+		// remove
+		// listner
+		// methods can change the actual instance of the listener array from
+		// another thread
+		if (fModelStateListeners != null) {
+			if (Logger.DEBUG_MODELSTATE) {
+				Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelDirtyStateChanged"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			Object[] holdListeners = fModelStateListeners;
+			for (int i = 0; i < holdListeners.length; i++) {
+				((IModelStateListener) holdListeners[i]).modelDirtyStateChanged(element, isDirty);
+			}
+		}
+	}
+
+	protected void fireModelReinitialized() {
+
+		// we must assign listeners to local variable, since the add and
+		// remove
+		// listner
+		// methods can change the actual instance of the listener array from
+		// another thread
+		if (fModelStateListeners != null) {
+			if (Logger.DEBUG_MODELSTATE) {
+				Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelReinitialized"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			Object[] holdListeners = fModelStateListeners;
+			for (int i = 0; i < holdListeners.length; i++) {
+				IModelStateListener listener = (IModelStateListener) holdListeners[i];
+				listener.modelReinitialized(this);
+			}
+		}
+	}
+
+	/**
+	 * Informs all registered model state listeners about the deletion of a
+	 * model's underlying resource.
+	 */
+	protected void fireModelResourceDeleted(IStructuredModel element) {
+
+		// we must assign listeners to local variable, since the add and
+		// remove
+		// listner
+		// methods can change the actual instance of the listener array from
+		// another thread
+		if (fModelStateListeners != null) {
+			if (Logger.DEBUG_MODELSTATE) {
+				Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelResourceDeleted"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			Object[] holdListeners = fModelStateListeners;
+			for (int i = 0; i < holdListeners.length; i++) {
+				((IModelStateListener) holdListeners[i]).modelResourceDeleted(element);
+			}
+		}
+	}
+
+	/**
+	 * Informs all registered model state listeners that the resource
+	 * underlying a model has been moved. This is typically reflected in a
+	 * change to the id, baseLocation, or both.
+	 */
+	protected void fireModelResourceMoved(IStructuredModel originalElement, IStructuredModel movedElement) {
+
+		// we must assign listeners to local variable, since the add and
+		// remove
+		// listner
+		// methods can change the actual instance of the listener array from
+		// another thread
+		if (fModelStateListeners != null) {
+			if (Logger.DEBUG_MODELSTATE) {
+				Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelResourceMoved"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			Object[] holdListeners = fModelStateListeners;
+			for (int i = 0; i < holdListeners.length; i++) {
+				((IModelStateListener) holdListeners[i]).modelResourceMoved(originalElement, movedElement);
+			}
+		}
+	}
+
+	public Object getAdapter(Class adapter) {
+
+		return Platform.getAdapterManager().getAdapter(this, adapter);
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public java.lang.String getBaseLocation() {
+
+		return fBaseLocation;
+	}
+
+	/**
+	 * @see org.eclipse.wst.sse.core.internal.provisional.IStructuredModel#getContentTypeIdentifier()
+	 */
+	public String getContentTypeIdentifier() {
+		if (fExplicitContentTypeIdentifier != null)
+			return fExplicitContentTypeIdentifier;
+		return fModelHandler.getAssociatedContentTypeId();
+	}
+
+	/**
+	 * 
+	 */
+	public FactoryRegistry getFactoryRegistry() {
+		if (factoryRegistry == null) {
+			factoryRegistry = new FactoryRegistry();
+		}
+		return factoryRegistry;
+	}
+
+	/**
+	 * The id is the id that the model manager uses to identify this model
+	 * 
+	 * @ISSUE - no one should need to know ID, so this should be default access eventually. 
+	 * If clients believe they do need ID, be sure to let us know (open a bug). 
+	 */
+	public String getId() {
+
+		return fId;
+	}
+
+	public abstract IndexedRegion getIndexedRegion(int offset);
+
+	/**
+	 * Gets the contentTypeDescription.
+	 * 
+	 * @return Returns a ContentTypeDescription
+	 */
+	public IModelHandler getModelHandler() {
+
+		return fModelHandler;
+	}
+
+
+	public IModelManager getModelManager() {
+
+		return _getModelManager();
+	}
+
+	/**
+	 * This function returns the reference count of underlying model.
+	 */
+	// TODO: try to refine the design not to use this function
+	public int getReferenceCount() {
+
+
+		if (getModelManager() == null)
+			return 0;
+		return getModelManager().getReferenceCount(getId());
+	}
+
+
+	/**
+	 * This function returns the reference count of underlying model.
+	 */
+	// TODO: try to refine the design not to use this function
+	public int getReferenceCountForEdit() {
+
+
+
+		if (getModelManager() == null)
+			return 0;
+		return getModelManager().getReferenceCountForEdit(getId());
+	}
+
+
+	/**
+	 * This function returns the reference count of underlying model.
+	 */
+	// TODO: try to refine the design not to use this function
+	public int getReferenceCountForRead() {
+
+
+
+		if (getModelManager() == null)
+			return 0;
+		return getModelManager().getReferenceCountForRead(getId());
+	}
+
+	public Object getReinitializeStateData() {
+
+		return reinitializeStateData;
+	}
+
+
+
+	public URIResolver getResolver() {
+
+		return fResolver;
+	}
+
+
+	public IStructuredDocument getStructuredDocument() {
+
+		IStructuredDocument result = null;
+		result = fStructuredDocument;
+		return result;
+	}
+
+	/**
+	 * Insert the method's description here. Creation date: (9/7/2001 2:30:26
+	 * PM)
+	 * 
+	 * @return long
+	 */
+	public long getSynchronizationStamp() {
+
+		return fSynchronizationStamp;
+	}
+
+	public IStructuredTextUndoManager getUndoManager() {
+
+		IStructuredTextUndoManager structuredTextUndoManager = null;
+		IStructuredDocument structuredDocument = getStructuredDocument();
+		if (structuredDocument == null) {
+			structuredTextUndoManager = null;
+		}
+		else {
+			structuredTextUndoManager = structuredDocument.getUndoManager();
+		}
+		return structuredTextUndoManager;
+	}
+
+	public void initId(String id) {
+		fId = id;
+	}
+
+	private final Object STATE_LOCK = new Object();
+
+	final protected void internalAboutToBeChanged() {
+		int state = 0;
+		// we always increment counter, for every request (so *must* receive
+		// corresponding number of 'changedModel' requests)
+		synchronized (STATE_LOCK) {
+			state = fModelStateChanging++;
+		}
+
+		// notice we only fire this event if we are not
+		// already in a model state changing sequence
+		if (state == 0) {
+
+			if (Logger.DEBUG_MODELSTATE) {
+				Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelAboutToBeChanged"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+
+			try {
+				fireModelAboutToBeChanged();
+			}
+			catch (Exception e) {
+				Logger.logException("Exception while notifying model state listers of about to change", e); //$NON-NLS-1$
+			}
+
+		}
+		
+	}
+
+	/**
+	 * Informs all registered model state listeners that an impending change
+	 * is now complete. This method must only be called by 'modelChanged'
+	 * since it keeps track of counts.
+	 */
+	final protected void internalModelChanged() {
+		int state = 0;
+		// always decrement
+		synchronized (STATE_LOCK) {
+			state = --fModelStateChanging;
+		}
+
+		// Check integrity
+		// to be less than zero is a programming error,
+		// but we'll reset to zero
+		// and try to continue
+		if (state < 0) {
+			state = 0;
+			throw new IllegalStateException("Program Error: modelStateChanging was less than zero"); //$NON-NLS-1$
+		}
+
+
+		// We only fire this event if all pending requests are done.
+		// That is, if we've received the same number of modelChanged as
+		// we have aboutToChangeModel.
+		if (state == 0) {
+			if (Logger.DEBUG_MODELSTATE) {
+				Logger.log(Logger.INFO, "IModelStateListener event for " + getId() + " : modelChanged"); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+
+			fireModelChanged();
+		}
+	}
+
+	public boolean isDirty() {
+
+		return fDirtyState;
+	}
+
+	/**
+	 * This method has very special purpose, its used in subclass
+	 * 'changedModel' to know when to do "ending" sorts of things, right
+	 * before a call to super.ChangedModel would in deed put the model in
+	 * 'end' state. Put another way, at the beginning of the subclasses's
+	 * changedModel, the isModelStateChanging is true, but at end, it will be
+	 * false. So, this method allows a small "peek ahead".
+	 */
+	protected boolean isModelChangeStateOnVergeOfEnding() {
+
+
+		return fModelStateChanging == 1;
+	}
+
+	/**
+	 * This method can be called to determine if the model is within a
+	 * "aboutToChange" and "changed" sequence.
+	 */
+	public boolean isModelStateChanging() {
+
+
+		return fModelStateChanging > 0;
+	}
+
+	public boolean isNew() {
+
+		return fNewState;
+	}
+
+	public boolean isReinitializationNeeded() {
+
+		return reinitializationNeeded;
+	}
+
+	public boolean isSaveNeeded() {
+
+
+		if (!isSharedForEdit())
+			return isDirty();
+		else
+			return false;
+	}
+
+
+	/**
+	 * This function returns true if there are other references to the
+	 * underlying model.
+	 */
+	public boolean isShared() {
+		if (getModelManager() == null)
+			return false;
+		return getModelManager().isShared(getId());
+	}
+
+
+	/**
+	 * This function returns true if there are other references to the
+	 * underlying model.
+	 */
+	public boolean isSharedForEdit() {
+
+
+		if (getModelManager() == null)
+			return false;
+		return getModelManager().isSharedForEdit(getId());
+	}
+
+
+	/**
+	 * This function returns true if there are other references to the
+	 * underlying model.
+	 */
+	public boolean isSharedForRead() {
+
+
+		if (getModelManager() == null)
+			return false;
+		return getModelManager().isSharedForRead(getId());
+	}
+
+
+	public void modelReinitialized() {
+
+
+		// notice this is just a public avenue to our protected method
+		fireModelReinitialized();
+	}
+
+	public IStructuredModel newInstance() throws IOException {
+
+		IStructuredModel newModel = null;
+		// we delegate to the model manager, so loader, etc., can be
+		// used.
+		newModel = getModelManager().createNewInstance(this);
+		return newModel;
+	}
+
+	public IStructuredModel reinit() {
+
+
+		IStructuredModel result = null;
+		if (fModelStateChanging == 0) {
+			try {
+				aboutToChangeModel();
+				aboutToReinitializeModel();
+				result = _getModelManager().reinitialize(this);
+			}
+			finally {
+				setReinitializeNeeded(false);
+				setReinitializeStateData(null);
+				modelReinitialized();
+				changedModel();
+			}
+		}
+		else {
+			if (Logger.DEBUG_MODELSTATE) {
+				Logger.log(Logger.INFO, "indeed!!!"); //$NON-NLS-1$
+			}
+		}
+		return result;
+	}
+
+
+	/**
+	 * This function allows the model to free up any resources it might be
+	 * using. In particular, itself, as stored in the IModelManager.
+	 */
+	public void releaseFromEdit() {
+
+
+		if (getModelManager() == null) {
+			throw new IllegalStateException(MODEL_MANAGER_NULL); //$NON-NLS-1$
+		}
+		else {
+			/*
+			 * Be sure to check the shared state before releasing. (Since
+			 * isShared assumes a count of 1 means not shared ... and we want
+			 * our '1' to be that one.) The problem, of course, is that
+			 * between pre-cycle notification and post-release notification,
+			 * the model could once again have become shared, rendering the
+			 * release notification incorrect.
+			 */
+			boolean isShared = isShared();
+
+			if (!isShared) {
+				signalPreLifeCycleEventRelease(this);
+			}
+
+			_getModelManager().releaseFromEdit(this);
+			if (!isShared) {
+				signalPostLifeCycleListenerRelease(this);
+			}
+		}
+
+	}
+
+	/**
+	 * This function allows the model to free up any resources it might be
+	 * using. In particular, itself, as stored in the IModelManager.
+	 */
+	public void releaseFromRead() {
+
+		if (getModelManager() == null) {
+			throw new IllegalStateException(MODEL_MANAGER_NULL); //$NON-NLS-1$
+		}
+		else {
+			/*
+			 * Be sure to check the shared state before releasing. (Since
+			 * isShared assumes a count of 1 means not shared ... and we want
+			 * our '1' to be that one.) The problem, of course, is that
+			 * between pre-cycle notification and post-release notification,
+			 * the model could once again have become shared, rendering the
+			 * release notification incorrect.
+			 */
+			boolean isShared = isShared();
+
+			if (!isShared) {
+				signalPreLifeCycleEventRelease(this);
+			}
+
+			_getModelManager().releaseFromRead(this);
+
+			if (!isShared) {
+				signalPostLifeCycleListenerRelease(this);
+			}
+		}
+	}
+
+
+	/**
+	 * This function replenishes the model with the resource without saving
+	 * any possible changes. It is used when one editor may be closing, and
+	 * specifially says not to save the model, but another "display" of the
+	 * model still needs to hang on to some model, so needs a fresh copy.
+	 */
+	public IStructuredModel reload(InputStream inputStream) throws IOException {
+		IStructuredModel result = null;
+		try {
+			aboutToChangeModel();
+			result = _getModelManager().reloadModel(getId(), inputStream);
+		}
+		catch (UnsupportedEncodingException e) {
+			// log for now, unless we find reason not to
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+		finally {
+			changedModel();
+		}
+		return result;
+	}
+
+	public void removeModelLifecycleListener(IModelLifecycleListener listener) {
+
+		// if manager is null, then none have been added, so
+		// no need to remove any
+		if (fLifecycleNotificationManager == null)
+			return;
+		synchronized (fListenerLock) {
+			fLifecycleNotificationManager.removeListener(listener);
+		}
+	}
+
+
+	public void removeModelStateListener(IModelStateListener listener) {
+
+		if (listener == null)
+			return;
+		if (fModelStateListeners == null)
+			return;
+		// if its not in the listeners, we'll ignore the request
+		synchronized (fListenerLock) {
+			if (Utilities.contains(fModelStateListeners, listener)) {
+				int oldSize = fModelStateListeners.length;
+				int newSize = oldSize - 1;
+				Object[] newListeners = new Object[newSize];
+				int index = 0;
+				for (int i = 0; i < oldSize; i++) {
+					if (fModelStateListeners[i] == listener) { // ignore
+					}
+					else {
+						// copy old to new if its not the one we are
+						// removing
+						newListeners[index++] = fModelStateListeners[i];
+					}
+				}
+				// now that we have a new array, let's switch it for the
+				// old
+				// one
+				fModelStateListeners = newListeners;
+			}
+		}
+	}
+
+
+	/**
+	 * A method that modifies the model's synchronization stamp to match the
+	 * resource. Turns out there's several ways of doing it, so this ensures a
+	 * common algorithm.
+	 */
+	public void resetSynchronizationStamp(IResource resource) {
+
+
+		setSynchronizationStamp(computeModificationStamp(resource));
+	}
+
+
+	/**
+	 * This API allows a client to initiate notification to all interested
+	 * parties that a model's underlying resource has been deleted.
+	 */
+	public void resourceDeleted() {
+
+
+		// notice this is just a public avenue to our protected method
+		fireModelResourceDeleted(this);
+	}
+
+
+	/**
+	 * This method allows a model client to initiate notification to all
+	 * interested parties that a model's underlying resource location has
+	 * changed. Note: we assume caller has already changed baseLocation, Id,
+	 * etc., since its really up to the client to determine what's "new" about
+	 * a moved model. Caution: 'this' and 'newModel' may be the same object.
+	 * This is the case for current working with FileModelProvider, but have
+	 * left the dual argument for future possibilities.
+	 */
+	public void resourceMoved(IStructuredModel newModel) {
+
+
+		// notice this is just a public avenue to our protected method
+		fireModelResourceMoved(this, newModel);
+	}
+
+
+	public void save() throws UnsupportedEncodingException, IOException, CoreException {
+
+		int type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.PRE_EVENT;
+		ModelLifecycleEvent modelLifecycleEvent = new ModelLifecycleEvent(this, type);
+		signalLifecycleEvent(modelLifecycleEvent);
+
+		try {
+			String stringId = getId();
+			_getModelManager().saveModel(stringId, EncodingRule.CONTENT_BASED);
+		}
+
+		finally {
+			// we put end notification in finally block, so even if
+			// error occurs during save, listeners are still notified,
+			// since their code could depend on receiving, to clean up
+			// some state, or coordinate other resources.
+			type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.POST_EVENT;
+			modelLifecycleEvent = new ModelLifecycleEvent(this, type);
+			signalLifecycleEvent(modelLifecycleEvent);
+		}
+	}
+
+
+	public void save(EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException {
+
+		int type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.PRE_EVENT;
+		ModelLifecycleEvent modelLifecycleEvent = new ModelLifecycleEvent(this, type);
+		signalLifecycleEvent(modelLifecycleEvent);
+
+		try {
+			String stringId = getId();
+			_getModelManager().saveModel(stringId, encodingRule);
+		}
+		finally {
+			// we put end notification in finally block, so even if
+			// error occurs during save, listeners are still notified,
+			// since their code could depend on receiving, to clean up
+			// some state, or coordinate other resources.
+			type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.POST_EVENT;
+			modelLifecycleEvent = new ModelLifecycleEvent(this, type);
+			signalLifecycleEvent(modelLifecycleEvent);
+		}
+	}
+
+
+	public void save(IFile iFile) throws UnsupportedEncodingException, IOException, CoreException {
+
+		int type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.PRE_EVENT;
+		ModelLifecycleEvent modelLifecycleEvent = new ModelLifecycleEvent(this, type);
+		signalLifecycleEvent(modelLifecycleEvent);
+
+		try {
+			String stringId = getId();
+			_getModelManager().saveModel(iFile, stringId, EncodingRule.CONTENT_BASED);
+		}
+
+		finally {
+			// we put end notification in finally block, so even if
+			// error occurs during save, listeners are still notified,
+			// since their code could depend on receiving, to clean up
+			// some state, or coordinate other resources.
+			type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.POST_EVENT;
+			modelLifecycleEvent = new ModelLifecycleEvent(this, type);
+			signalLifecycleEvent(modelLifecycleEvent);
+		}
+	}
+
+
+	public void save(IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException {
+
+		int type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.PRE_EVENT;
+		ModelLifecycleEvent modelLifecycleEvent = new ModelLifecycleEvent(this, type);
+		signalLifecycleEvent(modelLifecycleEvent);
+
+		try {
+			String stringId = getId();
+			_getModelManager().saveModel(iFile, stringId, encodingRule);
+		}
+		finally {
+			// we put end notificatioon in finally block, so even if
+			// error occurs during save, listeners are still notified,
+			// since their code could depend on receiving, to clean up
+			// some state, or coordinate other resources.
+			type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.POST_EVENT;
+			modelLifecycleEvent = new ModelLifecycleEvent(this, type);
+			signalLifecycleEvent(modelLifecycleEvent);
+		}
+	}
+
+
+	public void save(OutputStream outputStream) throws UnsupportedEncodingException, CoreException, IOException {
+
+		int type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.PRE_EVENT;
+		ModelLifecycleEvent modelLifecycleEvent = new ModelLifecycleEvent(this, type);
+		signalLifecycleEvent(modelLifecycleEvent);
+
+		try {
+			String stringId = getId();
+			_getModelManager().saveModel(stringId, outputStream, EncodingRule.CONTENT_BASED);
+		}
+
+		finally {
+			// we put end notification in finally block, so even if
+			// error occurs during save, listeners are still notified,
+			// since their code could depend on receiving, to clean up
+			// some state, or coordinate other resources.
+			type = ModelLifecycleEvent.MODEL_SAVED | ModelLifecycleEvent.POST_EVENT;
+			modelLifecycleEvent = new ModelLifecycleEvent(this, type);
+			signalLifecycleEvent(modelLifecycleEvent);
+		}
+	}
+
+
+	/**
+	 * This attribute is typically used to denote the model's underlying
+	 * resource.
+	 */
+	public void setBaseLocation(java.lang.String newBaseLocation) {
+		fBaseLocation = newBaseLocation;
+		if (fResolver != null) {
+			fResolver.setFileBaseLocation(newBaseLocation);
+		}
+	}
+
+	public void setContentTypeIdentifier(String contentTypeIdentifier) {
+		fExplicitContentTypeIdentifier = contentTypeIdentifier;
+	}
+
+	/**
+	 * 
+	 */
+	public void setDirtyState(boolean dirtyState) {
+
+		// no need to process (set or fire event), if same value
+		if (fDirtyState != dirtyState) {
+			// pre-change notification
+			int type = ModelLifecycleEvent.MODEL_DIRTY_STATE | ModelLifecycleEvent.PRE_EVENT;
+			ModelLifecycleEvent modelLifecycleEvent = new ModelLifecycleEvent(this, type);
+			signalLifecycleEvent(modelLifecycleEvent);
+
+
+			// the actual change
+			fDirtyState = dirtyState;
+
+			// old notification
+			// TODO: C3 remove old notification
+			if (fDirtyState == false) {
+				// if we are being set to not dirty (such as just been saved)
+				// then we need to start listening for changes
+				// again to know when to set state to true;
+				getStructuredDocument().addDocumentChangedListener(fDirtyStateWatcher);
+			}
+			fireModelDirtyStateChanged(this, dirtyState);
+
+
+			// post change notification
+			type = ModelLifecycleEvent.MODEL_DIRTY_STATE | ModelLifecycleEvent.POST_EVENT;
+			modelLifecycleEvent = new ModelLifecycleEvent(this, type);
+			signalLifecycleEvent(modelLifecycleEvent);
+		}
+	}
+
+	/**
+	 * @deprecated - will likely be deprecated soon, in favor of direct 'adds'
+	 *             ... but takes some redesign.
+	 */
+	public void setFactoryRegistry(FactoryRegistry factoryRegistry) {
+		this.factoryRegistry = factoryRegistry;
+	}
+
+	/**
+	 * The id is the id that the model manager uses to identify this model. If
+	 * it is being set here, it means the model manger is already managing the
+	 * model with another id, so we have to keep it in sync. This method calls
+	 * notifies listners, if they haven't been notified already, that a "model
+	 * state change" is about to occur.
+	 */
+	public void setId(String newId) throws ResourceInUse {
+
+
+		// It makes no sense, I don't think, to have an id of null, so
+		// we'll throw an illegal argument exception if someone trys. Note:
+		// the IModelManager could not manage a model with an id of null,
+		// since it uses hashtables, and you can't have a null id for a
+		// hashtable.
+		if (newId == null)
+			throw new IllegalArgumentException(SSECoreMessages.A_model_s_id_can_not_be_nu_EXC_); //$NON-NLS-1$ = "A model's id can not be null"
+		// To guard against throwing a spurious ResourceInUse exception,
+		// which can occur when two pieces of code both want to change the id,
+		// so the second request is spurious, we'll ignore any requests that
+		// attempt to change the id to what it already is ... note, we use
+		// 'equals', not identity ('==') so that things like
+		// strings can be used. This is the same criteria that ids are
+		// found in model manager -- well, actually, I just checked, and for
+		// the hashtable impl, the criteria uses .equals AND the condition
+		// that the hash values be identical (I'm assuming this is always
+		// true, if equals is true, for now, I'm not sure
+		// we can assume that hashtable will always be used, but in
+		// general, should match.)
+		//
+		if (newId.equals(fId))
+			return;
+		// we must guard against reassigning an id to one that we already
+		// are managing.
+		if (getModelManager() != null) {
+			boolean inUse = ((ModelManagerImpl)getModelManager()).isIdInUse(newId);
+			if (inUse) {
+				throw new ResourceInUse();
+			}
+		}
+		try {
+			// normal code path
+			aboutToChangeModel();
+			String oldId = fId;
+			fId = newId;
+			if (getModelManager() != null) {
+				// if managed and the id has changed, notify to
+				// IModelManager
+				// TODO: try to refine the design not to do that
+				if (oldId != null && newId != null && !newId.equals(oldId)) {
+					getModelManager().moveModel(oldId, newId);
+				}
+			}
+		}
+		finally {
+			// make sure this finally is only executed if 'about to Change
+			// model' has
+			// been executed.
+			changedModel();
+		}
+	}
+
+	/**
+	 * Sets the contentTypeDescription.
+	 * 
+	 * @param contentTypeDescription
+	 *            The contentTypeDescription to set
+	 */
+	public void setModelHandler(IModelHandler modelHandler) {
+
+		// no need to fire events if modelHandler has been null
+		// for this model --
+		// this is an attempt at initialization optimization and may need
+		// to change in future.
+		boolean trueChange = false;
+		if (fModelHandler != null)
+			trueChange = true;
+		if (trueChange) {
+			internalAboutToBeChanged();
+		}
+		fModelHandler = modelHandler;
+		if (trueChange) {
+			internalModelChanged();
+		}
+	}
+
+
+
+	public void setModelManager(IModelManager newModelManager) {
+
+		fModelManager = newModelManager;
+	}
+
+	/**
+	 * 
+	 */
+	public void setNewState(boolean newState) {
+
+		fNewState = newState;
+	}
+
+	/**
+	 * Sets a "flag" that reinitialization is needed.
+	 */
+	public void setReinitializeNeeded(boolean needed) {
+
+		reinitializationNeeded = needed;
+	}
+
+	/**
+	 * Holds any data that the reinit procedure might find useful in
+	 * reinitializing the model. This is handy, since the reinitialization may
+	 * not take place at once, and some "old" data may be needed to properly
+	 * undo previous settings. Note: the parameter was intentionally made to
+	 * be of type 'Object' so different models can use in different ways.
+	 */
+	public void setReinitializeStateData(Object object) {
+
+		reinitializeStateData = object;
+	}
+
+
+	public void setResolver(URIResolver newResolver) {
+
+		fResolver = newResolver;
+	}
+
+
+	public void setStructuredDocument(IStructuredDocument newStructuredDocument) {
+		boolean lifeCycleNotification = false;
+		if (fStructuredDocument != null) {
+			fStructuredDocument.removeDocumentChangedListener(fDirtyStateWatcher);
+			fStructuredDocument.removeDocumentAboutToChangeListener(fDocumentToModelNotifier);
+			fStructuredDocument.removeDocumentChangedListener(fDocumentToModelNotifier);
+			// prechange notification
+			lifeCycleNotification = true;
+			ModelLifecycleEvent modelLifecycleEvent = new DocumentChanged(ModelLifecycleEvent.PRE_EVENT, this, fStructuredDocument, newStructuredDocument);
+			signalLifecycleEvent(modelLifecycleEvent);
+		}
+
+		// hold for life cycle notification
+		IStructuredDocument previousDocument = fStructuredDocument;
+		// the actual change
+		fStructuredDocument = newStructuredDocument;
+
+
+		// at the super class level, we'll listen for structuredDocument
+		// changes
+		// so we can set our dirty state flag
+		if (fStructuredDocument != null) {
+			fStructuredDocument.addDocumentChangedListener(fDirtyStateWatcher);
+			fStructuredDocument.addDocumentAboutToChangeListener(fDocumentToModelNotifier);
+			fStructuredDocument.addDocumentChangedListener(fDocumentToModelNotifier);
+		}
+
+		if (lifeCycleNotification) {
+			// post change notification
+			ModelLifecycleEvent modelLifecycleEvent = new DocumentChanged(ModelLifecycleEvent.POST_EVENT, this, previousDocument, newStructuredDocument);
+			signalLifecycleEvent(modelLifecycleEvent);
+		}
+	}
+
+	/**
+	 * Insert the method's description here. Creation date: (9/7/2001 2:30:26
+	 * PM)
+	 * 
+	 * @param newSynchronizationStamp
+	 *            long
+	 */
+	protected void setSynchronizationStamp(long newSynchronizationStamp) {
+
+		fSynchronizationStamp = newSynchronizationStamp;
+	}
+
+	public void setUndoManager(IStructuredTextUndoManager undoManager) {
+
+		IStructuredDocument structuredDocument = getStructuredDocument();
+		if (structuredDocument == null) {
+			throw new IllegalStateException("document was null when undo manager set on model"); //$NON-NLS-1$
+		}
+		structuredDocument.setUndoManager(undoManager);
+	}
+
+	/**
+	 * To be called only by "friendly" classes, such as ModelManager, and
+	 * subclasses.
+	 */
+	void signalLifecycleEvent(ModelLifecycleEvent event) {
+		if (fLifecycleNotificationManager == null)
+			return;
+		fLifecycleNotificationManager.signalLifecycleEvent(event);
+	}
+
+	private void signalPostLifeCycleListenerRelease(IStructuredModel structuredModel) {
+		int type = ModelLifecycleEvent.MODEL_RELEASED | ModelLifecycleEvent.POST_EVENT;
+		// what's wrong with this design that a cast is needed here!?
+		ModelLifecycleEvent event = new ModelLifecycleEvent(structuredModel, type);
+		((AbstractStructuredModel) structuredModel).signalLifecycleEvent(event);
+	}
+
+	private void signalPreLifeCycleEventRelease(IStructuredModel structuredModel) {
+		int type = ModelLifecycleEvent.MODEL_RELEASED | ModelLifecycleEvent.PRE_EVENT;
+		// what's wrong with this design that a cast is needed here!?
+		ModelLifecycleEvent event = new ModelLifecycleEvent(structuredModel, type);
+		((AbstractStructuredModel) structuredModel).signalLifecycleEvent(event);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/FactoryRegistry.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/FactoryRegistry.java
new file mode 100644
index 0000000..d0303903
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/FactoryRegistry.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.model;
+
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+
+
+/**
+ * This class simply maintains the list of factories and returns singleton
+ * instances of them. Some "built in" types are automatically created form
+ * FactoryConfig, if not found registerd, but normally clients can/should
+ * register their own factories.
+ * 
+ * Not intended for clients to subclass or instantiate.
+ * 
+ */
+public final class FactoryRegistry {
+
+	private List factories;
+
+	/**
+	 * intentionally default access
+	 */
+	FactoryRegistry() {
+		super();
+
+	}
+
+	private List _getFactories() {
+
+		if (factories == null) {
+			// may need to use java.util.Collections.synchronizedList() if
+			// syncronization becomes
+			// necessary (and if so, remember to synchronize on factories)
+			factories = new ArrayList();
+		}
+		return factories;
+
+	}
+
+	public void addFactory(INodeAdapterFactory factory) {
+		_getFactories().add(factory);
+	}
+
+	public void clearFactories() {
+		factories.clear();
+	}
+
+	/*
+	 * @see FactoryRegistry#contains(Object)
+	 */
+	public boolean contains(Object type) {
+		boolean result = false;
+		// note: we're not using cloned list, so strictly speaking
+		// is not thread safe.
+		List internalList = _getFactories();
+		for (int i = 0; i < internalList.size(); i++) {
+			INodeAdapterFactory factory = (INodeAdapterFactory) internalList.get(i);
+			if (factory.isFactoryForType(type)) {
+				result = true;
+				break;
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Returns a shallow copy of the list of factories in the registry. Note:
+	 * this can not be used to add/remove factories. Its primarily provided
+	 * for those few cases where a list of factories must be copied from one
+	 * model and added to another.
+	 */
+	public List getFactories() {
+		// note: for object integrity, we don't let anyone get
+		// our main list (so they have to add through addFactory),
+		// but we will return a shallow "cloned" list.
+		List factoryList = new ArrayList(_getFactories());
+		return factoryList;
+	}
+
+	/**
+	 * This method is a not a pure resistry. Factories retrieved based on
+	 * their response to "isFactoryForType(type)". Note that if there is more
+	 * than one factory that can answer 'true' that the most recently added
+	 * factory is used.
+	 */
+	public INodeAdapterFactory getFactoryFor(Object type) {
+
+		INodeAdapterFactory result = null;
+		if (factories == null)
+			return null;
+		int listSize = factories.size();
+		for (int i = listSize - 1; i >= 0; i--) {
+			// It is the adapter factories responsibility to answer
+			// isFactoryForType so it gets choosen.
+			// Notice we are going through the list backwards to get the
+			// factory added last.
+			INodeAdapterFactory a = (INodeAdapterFactory) factories.get(i);
+			if (a.isFactoryForType(type)) {
+				result = a;
+				break;
+			}
+		}
+		return result;
+
+	}
+
+	/**
+	 * 
+	 */
+	public void release() {
+		// modified to work on copy of list, for V5PTF1
+		// send release to local copy of list
+		// of factories, since some factories, during
+		// their release function, may remove
+		// themselves from the registry.
+		List localList = getFactories();
+		for (int i = 0; i < localList.size(); i++) {
+			INodeAdapterFactory a = (INodeAdapterFactory) localList.get(i);
+			// To help bullet proof code, we'll catch and log
+			// any messages thrown by factories during release,
+			// but we'll attempt to keep going.
+			// In nearly all cases, though, such errors are
+			// severe for product/client, and need to be fixed.
+			try {
+				a.release();
+			}
+			catch (Exception e) {
+				Logger.logException("Program problem releasing factory" + a, e); //$NON-NLS-1$
+			}
+		}
+	}
+
+	/**
+	 * Removes a factory if it can be retrieved by getFactoryFor(type). If
+	 * there is more than one, all are removed. If there is none, the call
+	 * simply returns (that is, it is not considered an error).
+	 */
+	public void removeFactoriesFor(java.lang.Object type) {
+		if (factories != null) {
+			int listSize = factories.size();
+			// we'll go backwards through list, since we're removing, so
+			// 'size' change won't matter.
+			// Note: I'm assuming other items in the collection do not change
+			// position
+			// simply because another was removed.
+			for (int i = listSize - 1; i >= 0; i--) {
+				// It is the adapter factories responsibility to answer
+				// isFactoryForType so it gets choosen.
+				INodeAdapterFactory a = (INodeAdapterFactory) factories.get(i);
+				if (a.isFactoryForType(type)) {
+					factories.remove(a);
+				}
+			}
+		}
+	}
+
+	public void removeFactory(INodeAdapterFactory factory) {
+		_getFactories().remove(factory);
+
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/LifecycleNotificationManager.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/LifecycleNotificationManager.java
new file mode 100644
index 0000000..adcf010
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/LifecycleNotificationManager.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.model;
+
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLifecycleListener;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+
+
+/**
+ * For "internal use" only by AbstractStructuredModel
+ */
+
+class LifecycleNotificationManager {
+	private Object[] fListeners;
+
+	LifecycleNotificationManager() {
+		super();
+	}
+
+	/**
+	 * Adds a new copy of the given listener to the list of Life Cycle
+	 * Listeners.
+	 * 
+	 * Multiple copies of the same listener are allowed. This is required to
+	 * support threaded listener management properly and for model-driven move
+	 * to work. For example, two adds and a single remove should result in the
+	 * listener still listening for events.
+	 * 
+	 * @param listener
+	 */
+	void addListener(IModelLifecycleListener listener) {
+		if (Logger.DEBUG && Utilities.contains(fListeners, listener)) {
+			Logger.log(Logger.WARNING, "IModelLifecycleListener " + listener + " listening more than once"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		int oldSize = 0;
+		if (fListeners != null) {
+			// normally won't be null, but we need to be sure, for first
+			// time through
+			oldSize = fListeners.length;
+		}
+		int newSize = oldSize + 1;
+		Object[] newListeners = new Object[newSize];
+		if (fListeners != null) {
+			System.arraycopy(fListeners, 0, newListeners, 0, oldSize);
+		}
+		// add listener to last position
+		newListeners[newSize - 1] = listener;
+		//
+		// now switch new for old
+		fListeners = newListeners;
+	}
+
+	/**
+	 * Removes a single copy of the given listener from the list of Life Cycle
+	 * Listeners.
+	 * 
+	 * @param listener
+	 */
+	void removeListener(IModelLifecycleListener listener) {
+		if (Utilities.contains(fListeners, listener)) {
+			// if its not in the listeners, we'll ignore the request
+			int oldSize = fListeners.length;
+			int newSize = oldSize - 1;
+			Object[] newListeners = new Object[newSize];
+			int index = 0;
+			boolean removedOnce = false;
+			for (int i = 0; i < oldSize; i++) {
+				if (fListeners[i] == listener && !removedOnce) {
+					// ignore on the first match
+					removedOnce = true;
+				} else {
+					// copy old to new if it's not the one we are removing
+					newListeners[index++] = fListeners[i];
+				}
+			}
+			// now that we have a new array, let's switch it for the old
+			// one
+			fListeners = newListeners;
+		}
+		if (Logger.DEBUG && Utilities.contains(fListeners, listener)) {
+			Logger.log(Logger.WARNING, "IModelLifecycleListener " + listener + " removed once but still listening"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+
+	void signalLifecycleEvent(ModelLifecycleEvent event) {
+		if (Logger.DEBUG_LIFECYCLE) {
+			Logger.log(Logger.INFO, "ModelLifecycleEvent fired for " + event.getModel().getId() + ": " + event.toString()); //$NON-NLS-1$ //$NON-NLS-2$
+			System.out.println("ModelLifecycleEvent fired for " + event.getModel().getId() + ": " + event.toString()); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		// We must assign listeners to local variable, since the add and
+		// remove listener methods can change the actual instance of the
+		// listener array from another thread
+		if (fListeners != null) {
+			Object[] holdListeners = fListeners;
+			for (int i = 0; i < holdListeners.length; i++) {
+				IModelLifecycleListener listener = (IModelLifecycleListener) holdListeners[i];
+				// only one type of listener for now ... this could become
+				// more complex
+				if ((event.getInternalType() & ModelLifecycleEvent.PRE_EVENT) == ModelLifecycleEvent.PRE_EVENT) {
+					listener.processPreModelEvent(event);
+				}
+				if ((event.getInternalType() & ModelLifecycleEvent.POST_EVENT) == ModelLifecycleEvent.POST_EVENT) {
+					listener.processPostModelEvent(event);
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/ModelLifecycleEvent.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/ModelLifecycleEvent.java
new file mode 100644
index 0000000..def66d0
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/ModelLifecycleEvent.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.model;
+
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+
+/**
+ * This is an early version of a class that may change over the next few
+ * milestones.
+ */
+
+
+public class ModelLifecycleEvent {
+
+
+	// this list is for "public" consumption
+	public static final int MODEL_SAVED = 0x0001;
+	public static final int MODEL_RELEASED = 0x00002;
+	public static final int MODEL_DOCUMENT_CHANGED = 0x0003;
+	public static final int MODEL_DIRTY_STATE = 0x0004;
+	public static final int MODEL_REVERT= 0x0005;
+
+	// TODO: finish support for these
+	// following not implemented yet
+	public static final int MODEL_REINITIALIZED = 0x0006;
+	//public static final int ADAPTERS_NOTIFIED = 0x0007;
+	//public static final int MODEL_RESOURCE_MOVED = 0x0008;
+	//public static final int MODEL_RESOURCE_DELETED = 0x0009;
+
+	// This list (upper two bytes) is for only internal mechanisms and
+	// subclasses
+	// For simplicity they are "masked out" when client calls getType()
+	protected static final int PRE_EVENT = 0x0100;
+	private final static int MASK = 0x00FF;
+	protected static final int POST_EVENT = 0x0200;
+
+
+	private IStructuredModel fModel;
+	private int fType;
+
+	public ModelLifecycleEvent() {
+		super();
+	}
+
+	public ModelLifecycleEvent(int type) {
+		this();
+		fType = type;
+	}
+
+	public ModelLifecycleEvent(IStructuredModel structuredModel, int type) {
+		this(type);
+		fModel = structuredModel;
+	}
+
+	private String debugString(int type) {
+		String result = null;
+		switch (type & MASK) {
+			case MODEL_SAVED :
+				result = "MODEL_SAVED"; //$NON-NLS-1$
+				break;
+			case MODEL_RELEASED :
+				result = "MODEL_RELEASED"; //$NON-NLS-1$
+				break;
+			case MODEL_DOCUMENT_CHANGED :
+				result = "MODEL_DOCUMENT_CHANGED"; //$NON-NLS-1$
+				break;
+			case MODEL_DIRTY_STATE :
+				result = "MODEL_DIRTY_STATE"; //$NON-NLS-1$
+				break;
+			/*
+			 * case MODEL_REINITIALIZED : result = "MODEL_REINITIALIZED";
+			 * break; case MODEL_RELOADED : result = "MODEL_RELOADED"; break;
+			 * case ADAPTERS_NOTIFIED : result = "ADAPTERS_NOTIFIED"; break;
+			 * case MODEL_RESOURCE_MOVED : result = "MODEL_RESOURCE_MOVED";
+			 * break; case MODEL_RESOURCE_DELETED : result =
+			 * "MODEL_RESOURCE_DELETED"; break;
+			 */
+			default :
+				throw new IllegalStateException("ModelLifecycleEvent did not have valid type"); //$NON-NLS-1$
+		}
+		return result;
+	}
+
+	protected int getInternalType() {
+
+		return fType;
+	}
+
+	public IStructuredModel getModel() {
+
+		return fModel;
+	}
+
+	public int getType() {
+
+		// for now, we'll mask type to "public" ones this easy
+		// way ... but I know there must be a better way
+		return fType & MASK;
+	}
+
+	public String toString() {
+		String result = null;
+		result = "ModelLifecycleEvent: " + debugString(fType); //$NON-NLS-1$
+		return result;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/ModelManagerImpl.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/ModelManagerImpl.java
new file mode 100644
index 0000000..82c1854
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/ModelManagerImpl.java
@@ -0,0 +1,2160 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *  *     Frank Zigler/Web Performance, Inc. - 288196 - Deadlock in ModelManagerImpl after IOException
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.model;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.filebuffers.ITextFileBuffer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.jobs.ILock;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.wst.sse.core.internal.FileBufferModelManager;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.NullMemento;
+import org.eclipse.wst.sse.core.internal.SSECoreMessages;
+import org.eclipse.wst.sse.core.internal.SSECorePlugin;
+import org.eclipse.wst.sse.core.internal.document.DocumentReader;
+import org.eclipse.wst.sse.core.internal.document.IDocumentLoader;
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+import org.eclipse.wst.sse.core.internal.encoding.CodedStreamCreator;
+import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames;
+import org.eclipse.wst.sse.core.internal.encoding.ContentBasedPreferenceGateway;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingRule;
+import org.eclipse.wst.sse.core.internal.exceptions.MalformedOutputExceptionWithDetail;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry;
+import org.eclipse.wst.sse.core.internal.provisional.IModelLoader;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument;
+import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceAlreadyExists;
+import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceInUse;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+import org.eclipse.wst.sse.core.internal.util.ProjectResolver;
+import org.eclipse.wst.sse.core.internal.util.URIResolver;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+
+/**
+ * <p>Not intended to be subclassed, referenced or instantiated by clients.
+ * Clients should obtain an instance of the IModelManager interface through
+ * {@link StructuredModelManager#getModelManager()}.</p>
+ * 
+ * <p>This class is responsible for creating, retrieving, and caching
+ * StructuredModels It retrieves the cached objects by an id which is
+ * typically a String representing the resources URI. Note: Its important that
+ * all clients that share a resource do so using <b>identical </b>
+ * identifiers, or else different instances will be created and retrieved,
+ * even if they all technically point to the same resource on the file system.
+ * This class also provides a convenient place to register Model Loaders and
+ * Dumpers based on 'type'.</p>
+ */
+public class ModelManagerImpl implements IModelManager {
+
+	
+	
+	static class ReadEditType {
+		ReadEditType(String type) {
+		}
+	}
+
+	class SharedObject {
+		int referenceCountForEdit;
+		int referenceCountForRead;
+		volatile IStructuredModel theSharedModel;
+		final ILock LOAD_LOCK = Job.getJobManager().newLock();
+		volatile boolean initializing = true;
+		volatile boolean doWait = true;
+		// The field 'id' is only meant for debug
+		final String id;
+
+		SharedObject(String id) {
+			this.id=id;
+			// be aware, this lock will leak and cause the deadlock detector to be horrible if we never release it
+			LOAD_LOCK.acquire();
+		}
+
+		/**
+		 * Waits until this shared object has been attempted to be loaded. The
+		 * load is "attempted" because not all loads result in a model. However,
+		 * upon leaving this method, theShareModel variable is up-to-date.
+		 */
+		public void waitForLoadAttempt() {
+			final boolean allowInterrupt = PrefUtil.ALLOW_INTERRUPT_WAITING_THREAD;
+			final long timeLimit = (PrefUtil.WAIT_DELAY==0) ? Long.MAX_VALUE : PrefUtil.now() + PrefUtil.WAIT_DELAY;
+			final Job current = Job.getJobManager().currentJob();
+			boolean interrupted = false;
+			try {
+				while (initializing) {
+					if (current!=null) {
+						current.yieldRule(null);
+					}
+					try {
+						loop();
+					} catch (InterruptedException e) {
+						if (allowInterrupt) {
+							throw new OperationCanceledException("Waiting thread interrupted while waiting for model id: "+id + " to load");
+						} else {
+							interrupted=true;
+						}
+					}
+					if (PrefUtil.now() >= timeLimit	)
+						throw new OperationCanceledException("Waiting thread timeout exceeded while waiting for model id: "+id + " to load");
+				}
+			}
+			finally {
+				if (interrupted) {
+					Thread.currentThread().interrupt();
+				}
+			}
+		}
+
+		private void loop() throws InterruptedException {	
+			if (initializing) {
+				if (LOAD_LOCK.acquire(PrefUtil.WAIT_INTERVAL_MS)) {
+					// if we got the lock, but initializing is still not true the deadlock detector gave us
+					// the lock and caused reentrancy into this critical section. This is invalid and the 
+					// sign of a cyclical load attempt. In this case, we through an 
+					// OperationCanceledException in lew of entering a spin-loop. 
+					if (initializing) {
+						LOAD_LOCK.release();
+						throw new OperationCanceledException("Aborted cyclic load attempt for model with id: "+ id );
+					} else {
+						LOAD_LOCK.release();
+					}
+				}
+			}
+		}
+
+		/**
+		 * Flags this model as loaded. All waiting methods on
+		 * {@link #waitForLoadAttempt()} will proceed after this method returns.
+		 */
+		public void setLoaded() {
+			initializing = false;
+			LOAD_LOCK.release();
+		}
+	}
+
+	private Exception debugException = null;
+
+	/**
+	 * Our singleton instance
+	 */
+	private static ModelManagerImpl instance;
+	private final static int READ_BUFFER_SIZE = 4096;
+
+	/**
+	 * Not to be called by clients, will be made restricted access.
+	 * 
+	 * @return
+	 */
+	public synchronized static IModelManager getInstance() {
+
+		if (instance == null) {
+			instance = new ModelManagerImpl();
+		}
+		return instance;
+	}
+
+	/**
+	 * Our cache of managed objects
+	 */
+	private Map fManagedObjects;
+
+	private ModelHandlerRegistry fModelHandlerRegistry;
+	private final ReadEditType READ = new ReadEditType("read"); //$NON-NLS-1$
+	private final ReadEditType EDIT = new ReadEditType("edit"); //$NON-NLS-1$
+	
+	private final ILock SYNC = Job.getJobManager().newLock();
+	/**
+	 * Intentionally default access only.
+	 * 
+	 */
+	ModelManagerImpl() {
+		super();
+		fManagedObjects = new HashMap();
+		// To prevent deadlocks:  always acquire multiple locks in this order: SYNC, sharedObject. 
+		// DO NOT acquire a SYNC within a sharedObject lock, unless you already own the SYNC lock
+		// Tip: Try to hold the smallest number of locks you can
+	}
+
+	private IStructuredModel _commonCreateModel(IFile file, String id, IModelHandler handler, URIResolver resolver, ReadEditType rwType, EncodingRule encodingRule) throws IOException,CoreException {
+		SharedObject sharedObject = null;
+		
+		SYNC.acquire();
+		sharedObject = (SharedObject) fManagedObjects.get(id);
+		SYNC.release();
+		
+		while(true) {
+			if (sharedObject!=null) {
+				sharedObject.waitForLoadAttempt();
+			}
+			SYNC.acquire();
+			// we know this object's model has passed the load, however, we don't know 
+			// it's reference count status. It might have already been disposed. Or it could have 
+			// been disposed and a concurrent thread has already begun loading it, in which case
+			// we should use the sharedobject they are loading. 
+			// NOTE: This pattern is applied 3 times in this class, but only doc'd once. The logic is 
+			// exactly the same. 
+			SharedObject testObject = (SharedObject) fManagedObjects.get(id);
+			if (testObject==null) {
+				// null means it's been disposed, we need to do the work to reload it.
+				sharedObject = new SharedObject(id);
+				fManagedObjects.put(id, sharedObject);
+				SYNC.release();
+				_doCommonCreateModel(file, id, handler, resolver, rwType, encodingRule,
+						sharedObject);
+				break;
+			} else if (sharedObject == testObject) {
+				// if nothing happened, just increment the could and return the shared model
+				synchronized(sharedObject) {
+					if (sharedObject.theSharedModel!=null) {
+						_incrCount(sharedObject, rwType);
+					}
+				}
+				SYNC.release();
+				break;
+			} else {
+				// sharedObject != testObject which means the object we were waiting on has been disposed
+				// a replacement has already been placed in the managedObjects table. Through away our
+				// stale sharedObject and continue on with the one we got from the queue. Note: We don't know its
+				// state, so continue the waitForLoad-check loop. 
+				SYNC.release();
+				sharedObject = testObject;
+			}
+		}
+		
+		// we expect to always return something
+		if (sharedObject == null) {
+			debugException = new Exception("instance only for stack trace"); //$NON-NLS-1$
+			Logger.logException("Program Error: no model recorded for id " + id, debugException); //$NON-NLS-1$
+		}
+		
+		// note: clients must call release for each time they call get.
+		return sharedObject==null ? null : sharedObject.theSharedModel;
+	}
+
+	private void _decrCount(SharedObject sharedObject, ReadEditType type) {
+		if (type == READ) {
+			sharedObject.referenceCountForRead--;
+			FileBufferModelManager.getInstance().disconnect(sharedObject.theSharedModel.getStructuredDocument());
+		}
+		else if (type == EDIT) {
+			sharedObject.referenceCountForEdit--;
+			FileBufferModelManager.getInstance().disconnect(sharedObject.theSharedModel.getStructuredDocument());
+		}
+		else
+			throw new IllegalArgumentException();
+	}
+
+	private void _doCommonCreateModel(IFile file, String id, IModelHandler handler,
+			URIResolver resolver, ReadEditType rwType, EncodingRule encodingRule,
+			SharedObject sharedObject) throws CoreException, IOException {
+		// XXX: Does not integrate with FileBuffers
+		boolean doRemove = true;
+		try {
+		synchronized(sharedObject) {
+			InputStream inputStream = null;
+			IStructuredModel model = null;
+			try {
+				model = _commonCreateModel(id, handler, resolver);
+				IModelLoader loader = handler.getModelLoader();
+				inputStream = Utilities.getMarkSupportedStream(file.getContents(true));
+				loader.load(Utilities.getMarkSupportedStream(inputStream), model, encodingRule);
+			}
+			catch (ResourceInUse e) {
+				// impossible, since we've already found
+				handleProgramError(e);
+			} finally {
+				if (inputStream!=null) {
+					try { 
+						inputStream.close();
+					} catch(IOException e) {
+					}
+				}
+			}
+			if (model != null) {
+				// add to our cache
+				sharedObject.theSharedModel=model;
+				_initCount(sharedObject, rwType);
+				doRemove = false;
+			}
+		}
+		}
+		finally{
+		if (doRemove) {
+			SYNC.acquire();	
+			fManagedObjects.remove(id);	
+			SYNC.release();
+		}
+		sharedObject.setLoaded();
+		}
+	}
+
+	private IStructuredModel _commonCreateModel(InputStream inputStream, String id, IModelHandler handler, URIResolver resolver, ReadEditType rwType, String encoding, String lineDelimiter) throws IOException {
+		
+		if (id == null) {
+			throw new IllegalArgumentException("Program Error: id may not be null"); //$NON-NLS-1$
+		}
+		SharedObject sharedObject = null;
+	
+		SYNC.acquire();
+		sharedObject = (SharedObject) fManagedObjects.get(id);
+		SYNC.release();
+		
+		while(true) {
+			if (sharedObject!=null) {
+				sharedObject.waitForLoadAttempt();
+			}
+			SYNC.acquire();
+			SharedObject testObject = (SharedObject) fManagedObjects.get(id);
+			if (testObject==null) {
+				// it was removed ,so lets create it
+				sharedObject = new SharedObject(id);
+				fManagedObjects.put(id, sharedObject);
+				SYNC.release();
+				_doCommonCreateModel(inputStream, id, handler, resolver, rwType,
+						encoding, lineDelimiter, sharedObject);
+				break;
+			} else if (sharedObject == testObject) {
+				synchronized(sharedObject) {
+					if (sharedObject.theSharedModel!=null) {
+						_incrCount(sharedObject, rwType);
+					}
+				}
+				SYNC.release();
+				break;
+			} else {
+				SYNC.release();
+				sharedObject = testObject;
+			}
+		}
+		
+		// we expect to always return something
+		Assert.isNotNull(sharedObject, "Program Error: no model recorded for id " + id); //$NON-NLS-1$
+		// note: clients must call release for each time they call get.
+		return sharedObject.theSharedModel;
+	
+	}
+
+	private void _doCommonCreateModel(InputStream inputStream, String id, IModelHandler handler,
+			URIResolver resolver, ReadEditType rwType, String encoding, String lineDelimiter,
+			SharedObject sharedObject) throws IOException {
+		boolean doRemove = true;
+		try {
+		synchronized(sharedObject) {
+			IStructuredModel model = null;
+			try {
+				model = _commonCreateModel(id, handler, resolver);
+				IModelLoader loader = handler.getModelLoader();
+				if (inputStream == null) {
+					Logger.log(Logger.WARNING, "model was requested for id " + id + " without a content InputStream"); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+				loader.load(id, Utilities.getMarkSupportedStream(inputStream), model, encoding, lineDelimiter);
+			}
+			catch (ResourceInUse e) {
+				// impossible, since we've already found
+				handleProgramError(e);
+			}
+			if (model != null) {
+				/**
+				 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=264228
+				 * 
+				 * Ensure that the content type identifier field of the model
+				 * is properly set. This is normally handled by the
+				 * FileBufferModelManager when working with files as it knows
+				 * the content type in advance; here is where we handle it for
+				 * streams.
+				 */
+				if (model instanceof AbstractStructuredModel) {
+					DocumentReader reader = new DocumentReader(model.getStructuredDocument());
+					IContentDescription description = Platform.getContentTypeManager().getDescriptionFor(reader, id, new QualifiedName[0]);
+					reader.close();
+					if (description != null && description.getContentType() != null) {
+						((AbstractStructuredModel) model).setContentTypeIdentifier(description.getContentType().getId());
+					}
+				}
+
+				sharedObject.theSharedModel = model;
+				_initCount(sharedObject, rwType);
+				doRemove = false;
+			}
+		}
+		}
+		finally {
+		if (doRemove) {
+			SYNC.acquire();
+			// remove it if we didn't get one back
+			fManagedObjects.remove(id);
+			SYNC.release();
+		}
+		sharedObject.setLoaded();
+		}
+	}
+
+	private IStructuredModel _commonCreateModel(String id, IModelHandler handler, URIResolver resolver) throws ResourceInUse {
+
+		IModelLoader loader = handler.getModelLoader();
+		IStructuredModel result = loader.createModel();
+		// in the past, id was null for "unmanaged" case, so we won't
+		// try and set it
+		if (id != null) {
+			result.setId(id);
+		}
+		result.setModelHandler(handler);
+		result.setResolver(resolver);
+		// some obvious redunancy here that maybe could be improved
+		// in future, but is necessary for now
+		result.setBaseLocation(id);
+		if (resolver != null) {
+			resolver.setFileBaseLocation(id);
+		}
+		addFactories(result, handler);
+		return result;
+	}
+
+	private IStructuredModel _commonGetModel(IFile iFile, ReadEditType rwType, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException {
+		IStructuredModel model = null;
+
+		if (iFile != null && iFile.exists()) {
+			String id = calculateId(iFile);
+			IModelHandler handler = calculateType(iFile);
+			URIResolver resolver = calculateURIResolver(iFile);
+			model = _commonCreateModel(iFile, id, handler, resolver, rwType, encodingRule);
+		}
+
+		return model;
+	}
+
+	private IStructuredModel _commonGetModel(IFile iFile, ReadEditType rwType, String encoding, String lineDelimiter) throws UnsupportedEncodingException, IOException, CoreException {
+		String id = calculateId(iFile);
+		IStructuredModel model = _commonGetModel(iFile, id, rwType, encoding, lineDelimiter);
+
+		return model;
+	}
+
+	private IStructuredModel _commonGetModel(IFile file, String id, ReadEditType rwType, String encoding, String lineDelimiter) throws IOException, CoreException {
+		if (id == null)
+			throw new IllegalArgumentException("Program Error: id may not be null"); //$NON-NLS-1$
+
+		SharedObject sharedObject = null;
+		if (file != null && file.exists()) {
+			SYNC.acquire();
+			sharedObject = (SharedObject) fManagedObjects.get(id);
+			SYNC.release();
+			
+			while(true) {
+				if (sharedObject!=null) {
+					sharedObject.waitForLoadAttempt();
+				}
+				SYNC.acquire();
+				SharedObject testObject = (SharedObject) fManagedObjects.get(id);
+				if (testObject==null) {
+					// it was removed ,so lets create it
+					sharedObject = new SharedObject(id);
+					fManagedObjects.put(id, sharedObject);
+					
+					SYNC.release();
+					_doCommonGetModel(file, id, sharedObject,rwType);
+					break;
+				} else if (sharedObject == testObject) {
+					synchronized(sharedObject) {
+						if (sharedObject.theSharedModel!=null) {
+							_incrCount(sharedObject, rwType);
+						}
+					}
+					SYNC.release();
+					break;
+				} else {
+					// we got a different object than what we were expecting
+					SYNC.release();
+					// two threads were interested in models for the same id. 
+					// The other thread one, so lets back off and try again. 
+					sharedObject = testObject; 
+				}
+			}
+		}
+		
+		// if we don't know how to create a model
+		// for this type of file, return null
+	
+		// note: clients must call release for each time they call
+		// get.
+			
+		return sharedObject==null ? null : sharedObject.theSharedModel;
+	}
+
+	private void _doCommonGetModel(IFile file, String id, SharedObject sharedObject,ReadEditType rwType) {
+		boolean doRemove = true;
+		try {
+			synchronized(sharedObject) {
+				sharedObject.doWait=false;
+				IStructuredModel model = null;
+				try {
+					model = FileBufferModelManager.getInstance().getModel(file);
+				}
+				finally {
+					sharedObject.doWait=true;
+				}
+				if (model != null) {
+					sharedObject.theSharedModel=model;
+					_initCount(sharedObject, rwType);
+					doRemove = false;
+				}
+			}
+		}
+		finally {
+			if (doRemove) {
+				SYNC.acquire();
+				fManagedObjects.remove(id);
+				SYNC.release();
+			}
+			sharedObject.setLoaded();
+		}
+	}
+
+	private SharedObject _commonNewModel(IFile iFile, boolean force) throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException {
+		IStructuredModel aSharedModel = null;
+		// First, check if resource already exists on file system.
+		// if is does, then throw Resource in Use iff force==false
+
+		if (iFile.exists() && !force) {
+			throw new ResourceAlreadyExists();
+		}
+		
+		SharedObject sharedObject = null;
+		String id = calculateId(iFile);
+		try {
+			SYNC.acquire();
+		
+			 sharedObject = (SharedObject) fManagedObjects.get(id);
+	
+			if (sharedObject != null && !force) {
+				// if in cache already, and force is not true, then this is an
+				// error
+				// in call
+				throw new ResourceInUse();
+			}
+			
+			sharedObject = new SharedObject(id);
+			fManagedObjects.put(id, sharedObject);
+			
+		} finally {
+			SYNC.release();
+		}
+		
+		// if we get to here without above exceptions, then all is ok
+		// to get model like normal, but set 'new' attribute (where the
+		// 'new' attribute means this is a model without a corresponding
+		// underlying resource.
+		aSharedModel = FileBufferModelManager.getInstance().getModel(iFile);
+		aSharedModel.setNewState(true);
+		
+		sharedObject.theSharedModel=aSharedModel;
+		// when resource is provided, we can set
+		// synchronization stamp ... otherwise client should
+		// Note: one client which does this is FileModelProvider.
+		aSharedModel.resetSynchronizationStamp(iFile);
+		return sharedObject;
+	}
+
+	public IStructuredModel _getModelFor(IStructuredDocument document, ReadEditType accessType) {
+
+		String id = FileBufferModelManager.getInstance().calculateId(document);
+		if (id == null) {
+			if (READ == accessType)
+				return getExistingModelForRead(document);
+			if (EDIT == accessType)
+				return getExistingModelForEdit(document);
+			Assert.isNotNull(id, "unknown IStructuredDocument " + document); //$NON-NLS-1$
+		}
+		
+		SharedObject sharedObject = null;
+		SYNC.acquire();
+		sharedObject = (SharedObject) fManagedObjects.get(id);
+		SYNC.release();
+		
+		while(true) {
+			if (sharedObject!=null) {
+				sharedObject.waitForLoadAttempt();
+			}
+			SYNC.acquire();
+			SharedObject testObject = (SharedObject) fManagedObjects.get(id);
+			if (testObject==null) {
+				sharedObject = new SharedObject(id);
+				fManagedObjects.put(id, sharedObject);
+				SYNC.release();
+				synchronized(sharedObject) {
+					sharedObject.theSharedModel = FileBufferModelManager.getInstance().getModel(document);
+					_initCount(sharedObject, accessType);
+					sharedObject.setLoaded();
+				}
+				break;
+			} else if (sharedObject == testObject) {
+				synchronized(sharedObject) {
+					Assert.isTrue(sharedObject.referenceCountForEdit + sharedObject.referenceCountForRead > 0, "reference count was less than zero");
+					if (sharedObject.theSharedModel!=null) {
+						_incrCount(sharedObject, accessType);
+					}
+				}
+				SYNC.release();
+				break;
+			} else {
+				SYNC.release();
+				sharedObject = testObject;
+			}
+		}
+		
+		return sharedObject==null ? null : sharedObject.theSharedModel;
+	}
+
+	private void _incrCount(SharedObject sharedObject, ReadEditType type) {
+		synchronized(sharedObject) {
+			if (type == READ) {
+				sharedObject.referenceCountForRead++;
+				FileBufferModelManager.getInstance().connect(sharedObject.theSharedModel.getStructuredDocument());
+			}
+			else if (type == EDIT) {
+				sharedObject.referenceCountForEdit++;
+				FileBufferModelManager.getInstance().connect(sharedObject.theSharedModel.getStructuredDocument());
+			}
+			else
+				throw new IllegalArgumentException();
+		}
+	}
+
+	private void _initCount(SharedObject sharedObject, ReadEditType type) {
+		synchronized(sharedObject) {
+			if (type == READ) {
+				FileBufferModelManager.getInstance().connect(sharedObject.theSharedModel.getStructuredDocument());
+				sharedObject.referenceCountForRead = 1;
+			}
+			else if (type == EDIT) {
+				FileBufferModelManager.getInstance().connect(sharedObject.theSharedModel.getStructuredDocument());
+				sharedObject.referenceCountForEdit = 1;
+			}
+			else
+				throw new IllegalArgumentException();
+		}
+	}
+
+	private void addFactories(IStructuredModel model, IModelHandler handler) {
+		Assert.isNotNull(model, "model can not be null"); //$NON-NLS-1$
+		FactoryRegistry registry = model.getFactoryRegistry();
+		Assert.isNotNull(registry, "model's Factory Registry can not be null"); //$NON-NLS-1$
+		List factoryList = handler.getAdapterFactories();
+		addFactories(model, factoryList);
+	}
+
+	private void addFactories(IStructuredModel model, List factoryList) {
+		Assert.isNotNull(model, "model can not be null"); //$NON-NLS-1$
+		FactoryRegistry registry = model.getFactoryRegistry();
+		Assert.isNotNull(registry, "model's Factory Registry can not be null"); //$NON-NLS-1$
+		// Note: we add all of them from handler, even if
+		// already exists. May need to reconsider this.
+		if (factoryList != null) {
+			Iterator iterator = factoryList.iterator();
+			while (iterator.hasNext()) {
+				INodeAdapterFactory factory = (INodeAdapterFactory) iterator.next();
+				registry.addFactory(factory);
+			}
+		}
+	}
+
+
+	/**
+	 * Calculate id provides a common way to determine the id from the input
+	 * ... needed to get and save the model. It is a simple class utility, but
+	 * is an instance method so can be accessed via interface.
+	 */
+	public String calculateId(IFile file) {
+		return FileBufferModelManager.getInstance().calculateId(file);
+	}
+
+	private IModelHandler calculateType(IFile iFile) throws CoreException {
+		// IModelManager mm = ((ModelManagerPlugin)
+		// Platform.getPlugin(ModelManagerPlugin.ID)).getModelManager();
+		ModelHandlerRegistry cr = getModelHandlerRegistry();
+		IModelHandler cd = cr.getHandlerFor(iFile);
+		return cd;
+	}
+
+	private IModelHandler calculateType(String filename, InputStream inputStream) throws IOException {
+		ModelHandlerRegistry cr = getModelHandlerRegistry();
+		IModelHandler cd = cr.getHandlerFor(filename, inputStream);
+		return cd;
+	}
+
+	/**
+	 * 
+	 */
+	private URIResolver calculateURIResolver(IFile file) {
+		// Note: see comment in plugin.xml for potentially
+		// breaking change in behavior.
+
+		IProject project = file.getProject();
+		URIResolver resolver = (URIResolver) project.getAdapter(URIResolver.class);
+		if (resolver == null)
+			resolver = new ProjectResolver(project);
+		Object location = file.getLocation();
+		if (location == null)
+			location = file.getLocationURI();
+		if (location != null)
+			resolver.setFileBaseLocation(location.toString());
+		return resolver;
+	}
+
+	/*
+	 * Note: This method appears in both ModelManagerImpl and JSEditor (with
+	 * just a minor difference). They should be kept the same.
+	 * 
+	 * @deprecated - handled by platform
+	 */
+	private void convertLineDelimiters(IDocument document, IFile iFile) throws CoreException {
+		// Note: calculateType(iFile) returns a default xml model handler if
+		// content type is null.
+		String contentTypeId = calculateType(iFile).getAssociatedContentTypeId();
+		String endOfLineCode = ContentBasedPreferenceGateway.getPreferencesString(contentTypeId, CommonEncodingPreferenceNames.END_OF_LINE_CODE);
+		// endOfLineCode == null means the content type does not support this
+		// function (e.g. DTD)
+		// endOfLineCode == "" means no translation
+		if (endOfLineCode != null && endOfLineCode.length() > 0) {
+			String lineDelimiterToUse = System.getProperty("line.separator"); //$NON-NLS-1$
+			if (endOfLineCode.equals(CommonEncodingPreferenceNames.CR))
+				lineDelimiterToUse = CommonEncodingPreferenceNames.STRING_CR;
+			else if (endOfLineCode.equals(CommonEncodingPreferenceNames.LF))
+				lineDelimiterToUse = CommonEncodingPreferenceNames.STRING_LF;
+			else if (endOfLineCode.equals(CommonEncodingPreferenceNames.CRLF))
+				lineDelimiterToUse = CommonEncodingPreferenceNames.STRING_CRLF;
+
+			TextEdit multiTextEdit = new MultiTextEdit();
+			int lineCount = document.getNumberOfLines();
+			try {
+				for (int i = 0; i < lineCount; i++) {
+					IRegion lineInfo = document.getLineInformation(i);
+					int lineStartOffset = lineInfo.getOffset();
+					int lineLength = lineInfo.getLength();
+					int lineEndOffset = lineStartOffset + lineLength;
+
+					if (i < lineCount - 1) {
+						String currentLineDelimiter = document.getLineDelimiter(i);
+						if (currentLineDelimiter != null && currentLineDelimiter.compareTo(lineDelimiterToUse) != 0)
+							multiTextEdit.addChild(new ReplaceEdit(lineEndOffset, currentLineDelimiter.length(), lineDelimiterToUse));
+					}
+				}
+
+				if (multiTextEdit.getChildrenSize() > 0)
+					multiTextEdit.apply(document);
+			}
+			catch (BadLocationException exception) {
+				// just adding generic runtime here, until whole method
+				// deleted.
+				throw new RuntimeException(exception.getMessage());
+			}
+		}
+	}
+
+	/**
+	 * this used to be in loader, but has been moved here
+	 */
+	private IStructuredModel copy(IStructuredModel model, String newId) throws ResourceInUse {
+		IStructuredModel newModel = null;
+		IStructuredModel oldModel = model;
+		IModelHandler modelHandler = oldModel.getModelHandler();
+		IModelLoader loader = modelHandler.getModelLoader();
+		// newModel = loader.newModel();
+		newModel = loader.createModel(oldModel);
+		// newId, oldModel.getResolver(), oldModel.getModelManager());
+		newModel.setModelHandler(modelHandler);
+		// IStructuredDocument oldStructuredDocument =
+		// oldModel.getStructuredDocument();
+		// IStructuredDocument newStructuredDocument =
+		// oldStructuredDocument.newInstance();
+		// newModel.setStructuredDocument(newStructuredDocument);
+		newModel.setResolver(oldModel.getResolver());
+		newModel.setModelManager(oldModel.getModelManager());
+		// duplicateFactoryRegistry(newModel, oldModel);
+		newModel.setId(newId);
+		// set text of new one after all initialization is done
+		String contents = oldModel.getStructuredDocument().getText();
+		newModel.getStructuredDocument().setText(this, contents);
+		return newModel;
+	}
+
+	/**
+	 */
+	public IStructuredModel copyModelForEdit(String oldId, String newId) throws ResourceInUse {
+		IStructuredModel newModel = null;
+		// get the existing model associated with this id
+		IStructuredModel model = getExistingModel(oldId);
+		// if it doesn't exist, ignore request (though this would normally
+		// be a programming error.
+		if (model == null)
+			return null;
+		SharedObject sharedObject = null;
+		try {
+			SYNC.acquire();
+			// now be sure newModel does not exist
+			sharedObject = (SharedObject) fManagedObjects.get(newId);
+			if (sharedObject != null) {
+				throw new ResourceInUse();
+			}
+			sharedObject = new SharedObject(newId);
+			fManagedObjects.put(newId,sharedObject);
+		} finally {
+			SYNC.release();
+		}
+		// get loader based on existing type (note the type assumption)
+		// Object type = ((IStructuredModel) model).getType();
+		// IModelHandler type = model.getModelHandler();
+		// IModelLoader loader = (IModelLoader) getModelLoaders().get(type);
+		// IModelLoader loader = (IModelLoader) getModelLoaders().get(type);
+		// ask the loader to copy
+		synchronized(sharedObject) {
+			sharedObject.doWait = false;
+			newModel = copy(model, newId);
+			sharedObject.doWait = true;
+		}
+		if (newModel != null) {
+			// add to our cache
+			synchronized(sharedObject) {
+				sharedObject.theSharedModel=newModel;
+				sharedObject.referenceCountForEdit = 1;
+				trace("copied model", newId, sharedObject.referenceCountForEdit); //$NON-NLS-1$
+			}
+		} else {
+			SYNC.acquire();
+			fManagedObjects.remove(newId);
+			SYNC.release();
+		}
+		sharedObject.setLoaded();
+		return newModel;
+	}
+
+	/**
+	 * Similar to clone, except the new instance has no content. Note: this
+	 * produces an unmanaged model, for temporary use. If a true shared model
+	 * is desired, use "copy".
+	 */
+	public IStructuredModel createNewInstance(IStructuredModel oldModel) throws IOException {
+		IModelHandler handler = oldModel.getModelHandler();
+		IModelLoader loader = handler.getModelLoader();
+		IStructuredModel newModel = loader.createModel(oldModel);
+		newModel.setModelHandler(handler);
+		if (newModel instanceof AbstractStructuredModel) {
+			((AbstractStructuredModel) newModel).setContentTypeIdentifier(oldModel.getContentTypeIdentifier());
+		}
+		URIResolver oldResolver = oldModel.getResolver();
+		newModel.setResolver(oldResolver);
+		try {
+			newModel.setId(DUPLICATED_MODEL);
+		}
+		catch (ResourceInUse e) {
+			// impossible, since this is an unmanaged model
+		}
+		// base location should be null, but we'll set to
+		// null to be sure.
+		newModel.setBaseLocation(null);
+		return newModel;
+	}
+
+	/**
+	 * Factory method, since a proper IStructuredDocument must have a proper
+	 * parser assigned. Note: its assume that IFile does not actually exist as
+	 * a resource yet. If it does, ResourceAlreadyExists exception is thrown.
+	 * If the resource does already exist, then createStructuredDocumentFor is
+	 * the right API to use.
+	 * 
+	 * @throws ResourceInUse
+	 * 
+	 */
+	public  IStructuredDocument createNewStructuredDocumentFor(IFile iFile) throws ResourceAlreadyExists, IOException, CoreException {
+		if (iFile.exists()) {
+			throw new ResourceAlreadyExists(iFile.getFullPath().toOSString());
+		}
+		// Will reconsider in future version
+		// String id = calculateId(iFile);
+		// if (isResourceInUse(id)) {
+		// throw new ResourceInUse(iFile.getFullPath().toOSString());
+		// }
+		IDocumentLoader loader = null;
+		IModelHandler handler = calculateType(iFile);
+		loader = handler.getDocumentLoader();
+		// for this API, "createNew" we assume the IFile does not exist yet
+		// as checked above, so just create empty document.
+		IStructuredDocument result = (IStructuredDocument) loader.createNewStructuredDocument();
+		return result;
+	}
+
+	/**
+	 * Factory method, since a proper IStructuredDocument must have a proper
+	 * parser assigned. Note: clients should verify IFile exists before using
+	 * this method. If this IFile does not exist, then
+	 * createNewStructuredDocument is the correct API to use.
+	 * 
+	 * @throws ResourceInUse
+	 */
+	public  IStructuredDocument createStructuredDocumentFor(IFile iFile) throws IOException, CoreException {
+		if (!iFile.exists()) {
+			throw new FileNotFoundException(iFile.getFullPath().toOSString());
+		}
+		// Will reconsider in future version
+		// String id = calculateId(iFile);
+		// if (isResourceInUse(id)) {
+		// throw new ResourceInUse(iFile.getFullPath().toOSString());
+		// }
+		IDocumentLoader loader = null;
+		IModelHandler handler = calculateType(iFile);
+		loader = handler.getDocumentLoader();
+		IStructuredDocument result = (IStructuredDocument) loader.createNewStructuredDocument(iFile);
+		return result;
+	}
+
+	/**
+	 * Conveience method, since a proper IStructuredDocument must have a
+	 * proper parser assigned. It should only be used when an empty
+	 * structuredDocument is needed. Otherwise, use IFile form.
+	 * 
+	 * @deprecated - TODO: to be removed by C4 do we really need this? I
+	 *             recommend to - use createStructuredDocumentFor(filename,
+	 *             null, null) - the filename does not need to represent a
+	 *             real - file, but can take for form of dummy.jsp, test.xml,
+	 *             etc. - That way we don't hard code the handler, but specify
+	 *             we - want the handler that "goes with" a certain type of -
+	 *             file.
+	 */
+	public  IStructuredDocument createStructuredDocumentFor(String contentTypeId) {
+		IDocumentLoader loader = null;
+		ModelHandlerRegistry cr = getModelHandlerRegistry();
+		IModelHandler handler = cr.getHandlerForContentTypeId(contentTypeId);
+		if (handler == null)
+			Logger.log(Logger.ERROR, "Program error: no model handler found for " + contentTypeId); //$NON-NLS-1$
+		loader = handler.getDocumentLoader();
+		IStructuredDocument result = (IStructuredDocument) loader.createNewStructuredDocument();
+		return result;
+	}
+
+	/**
+	 * Conveience method, since a proper IStructuredDocument must have a
+	 * proper parser assigned.
+	 * 
+	 * @deprecated -- - TODO: to be removed by C4 I marked as deprecated to
+	 *             discouage use of this method. It does not really work for
+	 *             JSP fragments, since JSP Fragments need an IFile to
+	 *             correctly look up the content settings. Use IFile form
+	 *             instead.
+	 */
+	public IStructuredDocument createStructuredDocumentFor(String filename, InputStream inputStream, URIResolver resolver) throws IOException {
+		IDocumentLoader loader = null;
+		InputStream istream = Utilities.getMarkSupportedStream(inputStream);
+		if (istream != null) {
+			istream.reset();
+		}
+		IModelHandler handler = calculateType(filename, istream);
+		loader = handler.getDocumentLoader();
+		IStructuredDocument result = null;
+		if (inputStream == null) {
+			result = (IStructuredDocument) loader.createNewStructuredDocument();
+		}
+		else {
+			result = (IStructuredDocument) loader.createNewStructuredDocument(filename, istream);
+		}
+		return result;
+	}
+
+	/**
+	 * Special case method. This method was created for the special case where
+	 * there is an encoding for input stream that should override all the
+	 * normal rules for encoding. For example, if there is an encoding
+	 * (charset) specified in HTTP response header, then that encoding is used
+	 * to translate the input stream to a string, but then the normal encoding
+	 * rules are ignored, so that the string is not translated twice (for
+	 * example, if its an HTML "file", then even if it contains a charset in
+	 * meta tag, its ignored since its assumed its all correctly decoded by
+	 * the HTTP charset.
+	 */
+	public  IStructuredDocument createStructuredDocumentFor(String filename, InputStream inputStream, URIResolver resolver, String encoding) throws IOException {
+		String content = readInputStream(inputStream, encoding);
+		IStructuredDocument result = createStructuredDocumentFor(filename, content, resolver);
+		return result;
+	}
+
+	/**
+	 * Convenience method. This method can be used when the resource does not
+	 * really exist (e.g. when content is being created, but hasn't been
+	 * written to disk yet). Note that since the content is being provided as
+	 * a String, it is assumed to already be decoded correctly so no
+	 * transformation is done.
+	 */
+	public  IStructuredDocument createStructuredDocumentFor(String filename, String content, URIResolver resolver) throws IOException {
+		// TODO: avoid all these String instances
+		StringBuffer contentBuffer = new StringBuffer(content);
+		IDocumentLoader loader = null;
+		IModelHandler handler = calculateType(filename, null);
+		loader = handler.getDocumentLoader();
+		IStructuredDocument result = (IStructuredDocument) loader.createNewStructuredDocument();
+		StringBuffer convertedContent = loader.handleLineDelimiter(contentBuffer, result);
+		result.setEncodingMemento(new NullMemento());
+		result.setText(this, convertedContent.toString());
+		return result;
+	}
+
+	/**
+	 * @param iFile
+	 * @param result
+	 * @return
+	 * @throws CoreException
+	 */
+	private IStructuredModel createUnManagedEmptyModelFor(IFile iFile) throws CoreException {
+		IStructuredModel result = null;
+		IModelHandler handler = calculateType(iFile);
+		String id = calculateId(iFile);
+		URIResolver resolver = calculateURIResolver(iFile);
+
+		try {
+			result = _commonCreateModel(id, handler, resolver);
+		}
+		catch (ResourceInUse e) {
+			// impossible, since we're not sharing
+			// (even if it really is in use ... we don't care)
+			// this may need to be re-examined.
+			if (Logger.DEBUG_MODELMANAGER)
+				Logger.log(Logger.INFO, "ModelMangerImpl::createUnManagedStructuredModelFor. Model unexpectedly in use."); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+
+		return result;
+	}
+
+	/**
+	 * Conveience method. It depends on the loaders newModel method to return
+	 * an appropriate StrucuturedModel appropriately initialized.
+	 */
+	public IStructuredModel createUnManagedStructuredModelFor(IFile iFile) throws IOException, CoreException {
+		IStructuredModel result = null;
+		result = createUnManagedEmptyModelFor(iFile);
+
+		IDocumentLoader loader = result.getModelHandler().getDocumentLoader();
+		IEncodedDocument document = loader.createNewStructuredDocument(iFile);
+
+		result.getStructuredDocument().setText(this, document.get());
+
+		return result;
+	}
+
+	/**
+	 * Conveience method. It depends on the loaders newModel method to return
+	 * an appropriate StrucuturedModel appropriately initialized.
+	 */
+	public  IStructuredModel createUnManagedStructuredModelFor(String contentTypeId) {
+		return createUnManagedStructuredModelFor(contentTypeId, null);
+	}
+
+	/**
+	 * Conveience method. It depends on the loaders newModel method to return
+	 * an appropriate StrucuturedModel appropriately initialized.
+	 */
+	public  IStructuredModel createUnManagedStructuredModelFor(String contentTypeId, URIResolver resolver) {
+		IStructuredModel result = null;
+		ModelHandlerRegistry cr = getModelHandlerRegistry();
+		IModelHandler handler = cr.getHandlerForContentTypeId(contentTypeId);
+		try {
+			result = _commonCreateModel(UNMANAGED_MODEL, handler, resolver); //$NON-NLS-1$
+		}
+		catch (ResourceInUse e) {
+			// impossible, since we're not sharing
+			// (even if it really is in use ... we don't care)
+			// this may need to be re-examined.
+			if (Logger.DEBUG_MODELMANAGER)
+				Logger.log(Logger.INFO, "ModelMangerImpl::createUnManagedStructuredModelFor. Model unexpectedly in use."); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		return result;
+	}
+
+	private IStructuredModel getExistingModel(Object id) {
+		IStructuredModel result = null;
+		
+		SYNC.acquire();
+		/**
+		 * While a good check in theory, it's possible for an event fired to
+		 * cause a listener to access a method that calls this one.
+		 */
+		//Assert.isTrue(SYNC.getDepth()==1, "depth not equal to 1");
+		// let's see if we already have it in our cache
+		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
+		// if not, then we'll simply return null
+		if (sharedObject != null) {
+			SYNC.release();
+			sharedObject.waitForLoadAttempt();
+			result = sharedObject.theSharedModel;
+		} else {
+			SYNC.release();
+		}
+		
+		return result;
+	}
+
+	/**
+	 * Note: users of this 'model' must still release it when finished.
+	 * Returns null if there's not a model corresponding to document.
+	 */
+	public IStructuredModel getExistingModelForEdit(IDocument document) {
+		IStructuredModel result = null;
+		
+		SYNC.acquire();		
+		// create a snapshot
+		Set ids = new HashSet(fManagedObjects.keySet());
+		SYNC.release();
+		for (Iterator iterator = ids.iterator(); iterator.hasNext();) {
+			Object potentialId = iterator.next();
+			SYNC.acquire();	
+			if (fManagedObjects.containsKey(potentialId)) {
+				// check to see if still valid
+				SYNC.release();
+				IStructuredModel tempResult = getExistingModel(potentialId);
+				if (tempResult!=null && document == tempResult.getStructuredDocument()) {
+					result = getExistingModelForEdit(potentialId);
+					break;
+				}
+			} else {
+				SYNC.release();
+			}
+		}
+		
+		return result;
+	}
+
+	/**
+	 * This is similar to the getModel method, except this method does not
+	 * create a model. This method does increment the reference count (if it
+	 * exists). If the model does not already exist in the cache of models,
+	 * null is returned.
+	 */
+	public  IStructuredModel getExistingModelForEdit(IFile iFile) {
+
+		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
+		Object id = calculateId(iFile);
+		IStructuredModel result = getExistingModelForEdit(id);
+		return result;
+	}
+
+	/**
+	 * This is similar to the getModel method, except this method does not
+	 * create a model. This method does increment the reference count (if it
+	 * exists). If the model does not already exist in the cache of models,
+	 * null is returned.
+	 * 
+	 * @deprecated use IFile form - this one will become protected or private
+	 */
+	public IStructuredModel getExistingModelForEdit(Object id) {
+
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+		IStructuredModel result = null;
+		boolean doRelease = true;
+		// let's see if we already have it in our cache
+		try {
+			SYNC.acquire();
+			SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
+			// if not, then we'll simply return null
+			if (sharedObject != null) {
+				// if shared object is in our cache, then simply increment its ref
+				// count,
+				// and return the object.
+				SYNC.release();
+				doRelease=false;
+				synchronized(sharedObject) {
+					if (sharedObject.doWait) {
+						sharedObject.waitForLoadAttempt();
+					}
+					if (sharedObject.theSharedModel!=null) {
+						_incrCount(sharedObject, EDIT);
+					}
+					result = sharedObject.theSharedModel;
+				}
+				trace("got existing model for Edit: ", id); //$NON-NLS-1$
+				trace("   incremented referenceCountForEdit ", id, sharedObject.referenceCountForEdit); //$NON-NLS-1$
+			}
+		} finally {
+			if (doRelease) {
+				SYNC.release();
+			}
+		}
+		
+		return result;
+	}
+
+	/**
+	 * Note: users of this 'model' must still release it when finished.
+	 * Returns null if there's not a model corresponding to document.
+	 */
+	public IStructuredModel getExistingModelForRead(IDocument document) {
+		IStructuredModel result = null;
+		
+		SYNC.acquire();		
+		// create a snapshot
+		Set ids = new HashSet(fManagedObjects.keySet());
+		SYNC.release();
+		for (Iterator iterator = ids.iterator(); iterator.hasNext();) {
+			Object potentialId = iterator.next();
+			SYNC.acquire();	
+			if (fManagedObjects.containsKey(potentialId)) {
+				// check to see if still valid
+				SYNC.release();
+				IStructuredModel tempResult = getExistingModel(potentialId);
+				if (tempResult!=null && document == tempResult.getStructuredDocument()) {
+					result = getExistingModelForRead(potentialId);
+					break;
+				}
+			} else {
+				SYNC.release();
+			}
+		}
+		
+		return result;
+	}
+
+	public IStructuredModel getExistingModelForRead(IFile iFile) {
+
+		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
+		Object id = calculateId(iFile);
+		IStructuredModel result = getExistingModelForRead(id);
+		return result;
+	}
+
+	/**
+	 * This is similar to the getModel method, except this method does not
+	 * create a model. This method does increment the reference count (if it
+	 * exists). If the model does not already exist in the cache of models,
+	 * null is returned.
+	 * 
+	 * @deprecated use IFile form - this one will become protected or private
+	 */
+	public  IStructuredModel getExistingModelForRead(Object id) {
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+		IStructuredModel result = null;
+		boolean doRelease = true;
+		// let's see if we already have it in our cache
+		try {
+			SYNC.acquire();
+			SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
+			// if not, then we'll simply return null
+			if (sharedObject != null) {
+				// if shared object is in our cache, then simply increment its ref
+				// count,
+				// and return the object.
+				SYNC.release();
+				doRelease=false;
+
+				synchronized(sharedObject) {
+					if (sharedObject.doWait) {
+						sharedObject.waitForLoadAttempt();
+					}
+					if (sharedObject.theSharedModel!=null) {
+						_incrCount(sharedObject, READ);
+					}
+					result = sharedObject.theSharedModel;
+				}
+			}
+		} finally {
+			if (doRelease)
+				SYNC.release();
+		}
+		return result;
+	}
+
+	/**
+	 * @deprecated DMW: Tom, this is "special" for links builder Assuming its
+	 *             still needed, wouldn't it be better to change to
+	 *             getExistingModels()? -- will be removed. Its not thread
+	 *             safe for one thread to get the Enumeration, when underlying
+	 *             data could be changed in another thread.
+	 */
+	public  Enumeration getExistingModelIds() {
+		try {
+			SYNC.acquire();
+			// create a copy
+			Vector keys = new Vector( fManagedObjects.keySet() );
+			return keys.elements();
+		} finally {
+			SYNC.release();
+		}
+	}
+
+	// TODO: replace (or supplement) this is a "model info" association to the
+	// IFile that created the model
+	private IFile getFileFor(IStructuredModel model) {
+		if (model == null)
+			return null;
+		String path = model.getBaseLocation();
+		if (path == null || path.length() == 0) {
+			Object id = model.getId();
+			if (id == null)
+				return null;
+			path = id.toString();
+		}
+		// TOODO needs rework for linked resources
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IFile file = root.getFileForLocation(new Path(path));
+		return file;
+	}
+
+	/**
+	 * One of the primary forms to get a managed model
+	 */
+	public  IStructuredModel getModelForEdit(IFile iFile) throws IOException, CoreException {
+		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
+		return _commonGetModel(iFile, EDIT, null, null);
+	}
+
+	public  IStructuredModel getModelForEdit(IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException {
+
+		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
+		return _commonGetModel(iFile, EDIT, encodingRule);
+	}
+
+	public  IStructuredModel getModelForEdit(IFile iFile, String encoding, String lineDelimiter) throws java.io.UnsupportedEncodingException, IOException, CoreException {
+
+		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
+		return _commonGetModel(iFile, EDIT, encoding, lineDelimiter);
+	}
+
+	public  IStructuredModel getModelForEdit(IStructuredDocument document) {
+		return _getModelFor(document, EDIT);
+	}
+
+	/**
+	 * @see IModelManager
+	 * @deprecated use IFile or String form
+	 */
+	public  IStructuredModel getModelForEdit(Object id, InputStream inputStream, URIResolver resolver) throws java.io.UnsupportedEncodingException, IOException {
+
+		Assert.isNotNull(id, "requested model id can not be null"); //$NON-NLS-1$
+		String stringId = id.toString();
+		return getModelForEdit(stringId, Utilities.getMarkSupportedStream(inputStream), resolver);
+	}
+
+	/**
+	 * @see IModelManager
+	 * @deprecated - use IFile or String form
+	 */
+	public  IStructuredModel getModelForEdit(Object id, Object modelType, String encodingName, String lineDelimiter, InputStream inputStream, URIResolver resolver) throws java.io.UnsupportedEncodingException, IOException {
+
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+		String stringId = id.toString();
+		return getModelForEdit(stringId, Utilities.getMarkSupportedStream(inputStream), resolver);
+	}
+
+	public  IStructuredModel getModelForEdit(String id, InputStream inputStream, URIResolver resolver) throws IOException {
+		if (id == null) {
+			throw new IllegalArgumentException("Program Error: id may not be null"); //$NON-NLS-1$
+		}
+		IStructuredModel result = null;
+
+		InputStream istream = Utilities.getMarkSupportedStream(inputStream);
+		IModelHandler handler = calculateType(id, istream);
+		if (handler != null) {
+			result = _commonCreateModel(istream, id, handler, resolver, EDIT, null, null);
+		}
+		else {
+			Logger.log(Logger.INFO, "no model handler found for id"); //$NON-NLS-1$
+		}
+		return result;
+	}
+
+	/**
+	 * One of the primary forms to get a managed model
+	 */
+	public  IStructuredModel getModelForRead(IFile iFile) throws IOException, CoreException {
+
+		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
+		return _commonGetModel(iFile, READ, null, null);
+	}
+
+	public  IStructuredModel getModelForRead(IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException {
+		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
+		return _commonGetModel(iFile, READ, encodingRule);
+	}
+
+	public  IStructuredModel getModelForRead(IFile iFile, String encodingName, String lineDelimiter) throws java.io.UnsupportedEncodingException, IOException, CoreException {
+		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
+		return _commonGetModel(iFile, READ, encodingName, lineDelimiter);
+	}
+
+	public  IStructuredModel getModelForRead(IStructuredDocument document) {
+		return _getModelFor(document, READ);
+	}
+
+	/**
+	 * @see IModelManager
+	 * @deprecated use IFile or String form
+	 */
+	public  IStructuredModel getModelForRead(Object id, InputStream inputStream, URIResolver resolver) throws java.io.UnsupportedEncodingException, IOException {
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+		String stringId = id.toString();
+		return getModelForRead(stringId, Utilities.getMarkSupportedStream(inputStream), resolver);
+	}
+
+	/**
+	 * @see IModelManager
+	 * @deprecated use IFile form
+	 */
+	public  IStructuredModel getModelForRead(Object id, Object modelType, String encodingName, String lineDelimiter, InputStream inputStream, URIResolver resolver) throws java.io.UnsupportedEncodingException, IOException {
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+		String stringId = id.toString();
+		return getModelForRead(stringId, Utilities.getMarkSupportedStream(inputStream), resolver);
+	}
+
+	public  IStructuredModel getModelForRead(String id, InputStream inputStream, URIResolver resolver) throws IOException {
+		InputStream istream = Utilities.getMarkSupportedStream(inputStream);
+		IModelHandler handler = calculateType(id, istream);
+		IStructuredModel result = null;
+		result = _commonCreateModel(istream, id, handler, resolver, READ, null, null);
+		return result;
+	}
+
+	/**
+	 * @deprecated - only temporarily visible
+	 */
+	public ModelHandlerRegistry getModelHandlerRegistry() {
+		if (fModelHandlerRegistry == null) {
+			fModelHandlerRegistry = ModelHandlerRegistry.getInstance();
+		}
+		return fModelHandlerRegistry;
+	}
+
+	/**
+	 * @see IModelManager#getNewModelForEdit(IFile, boolean)
+	 */
+	public  IStructuredModel getNewModelForEdit(IFile iFile, boolean force) throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException {
+		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
+		SharedObject sharedObject = _commonNewModel(iFile, force);
+		synchronized(sharedObject) {
+			sharedObject.referenceCountForEdit = 1;
+		}
+		sharedObject.setLoaded();
+		return sharedObject.theSharedModel;
+	}
+
+	/**
+	 * @see IModelManager#getNewModelForRead(IFile, boolean)
+	 */
+	public  IStructuredModel getNewModelForRead(IFile iFile, boolean force) throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException {
+
+		Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$
+		SharedObject sharedObject = _commonNewModel(iFile, force);
+		SYNC.acquire();
+		synchronized(sharedObject) {
+			if (sharedObject.theSharedModel!=null) {
+				sharedObject.referenceCountForRead = 1;
+			}
+		}
+		SYNC.release();
+		sharedObject.setLoaded();
+		return sharedObject.theSharedModel;
+	}
+
+	/**
+	 * This function returns the reference count of underlying model.
+	 * 
+	 * @param id
+	 *            Object The id of the model TODO: try to refine the design
+	 *            not to use this function
+	 */
+	public  int getReferenceCount(Object id) {
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+		int count = 0;
+	
+		SYNC.acquire();
+		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
+		if (sharedObject != null) {
+			SYNC.release();
+			sharedObject.waitForLoadAttempt();
+			synchronized (sharedObject) {
+				count = sharedObject.referenceCountForRead + sharedObject.referenceCountForEdit;
+			}
+		} else {
+			SYNC.release();
+		}
+		return count;
+	}
+
+	/**
+	 * This function returns the reference count of underlying model.
+	 * 
+	 * @param id
+	 *            Object The id of the model TODO: try to refine the design
+	 *            not to use this function
+	 */
+	public int getReferenceCountForEdit(Object id) {
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+		int count = 0;
+		SYNC.acquire();
+		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
+		if (sharedObject != null) {
+			SYNC.release();
+			sharedObject.waitForLoadAttempt();
+			synchronized(sharedObject) {
+				count = sharedObject.referenceCountForEdit;
+			}
+		} else {
+			SYNC.release();
+		}
+		return count;
+	}
+
+	/**
+	 * This function returns the reference count of underlying model.
+	 * 
+	 * @param id
+	 *            Object The id of the model TODO: try to refine the design
+	 *            not to use this function
+	 */
+	public int getReferenceCountForRead(Object id) {
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+		int count = 0;
+		SYNC.acquire();
+		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
+		if (sharedObject != null) {
+			SYNC.release();
+			sharedObject.waitForLoadAttempt();
+			synchronized(sharedObject) {
+				count = sharedObject.referenceCountForRead;
+			}
+		} else {
+			SYNC.release();
+		}
+		return count;
+	}
+
+	private void handleConvertLineDelimiters(IStructuredDocument structuredDocument, IFile iFile, EncodingRule encodingRule, EncodingMemento encodingMemento) throws CoreException, MalformedOutputExceptionWithDetail, UnsupportedEncodingException {
+		if (structuredDocument.getNumberOfLines() > 1) {
+			convertLineDelimiters(structuredDocument, iFile);
+		}
+	}
+
+	private void handleProgramError(Throwable t) {
+
+		Logger.logException("Impossible Program Error", t); //$NON-NLS-1$
+	}
+
+	/**
+	 * This function returns true if there are other references to the
+	 * underlying model.
+	 */
+	public  boolean isShared(Object id) {
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+		int count = 0;
+		boolean result = false;
+		SYNC.acquire();
+		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
+		if (sharedObject != null) {
+			SYNC.release();
+			sharedObject.waitForLoadAttempt();
+			synchronized(sharedObject) {
+				count = sharedObject.referenceCountForRead + sharedObject.referenceCountForEdit;
+			}
+		} else {
+			SYNC.release();
+		}
+		result = count > 1;
+		return result;
+	}
+
+	/**
+	 * This function returns true if there are other references to the
+	 * underlying model.
+	 * 
+	 * @param id
+	 *            Object The id of the model
+	 */
+	public  boolean isSharedForEdit(Object id) {
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+		int count = 0;
+		boolean result = false;
+		SYNC.acquire();
+		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
+		if (sharedObject != null) {
+			SYNC.release();
+			sharedObject.waitForLoadAttempt();
+			synchronized(sharedObject) {
+				count = sharedObject.referenceCountForEdit;
+			}
+		} else {
+			SYNC.release();
+		}
+		result = count > 1;
+		return result;
+	}
+
+	/**
+	 * This function returns true if there are other references to the
+	 * underlying model.
+	 * 
+	 * @param id
+	 *            Object The id of the model
+	 */
+	public  boolean isSharedForRead(Object id) {
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+		int count = 0;
+		boolean result = false;
+		SYNC.acquire();
+		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
+		if (sharedObject != null) {
+			SYNC.release();
+			sharedObject.waitForLoadAttempt();
+			synchronized(sharedObject) {
+				count = sharedObject.referenceCountForRead;
+			}
+		} else {
+			SYNC.release();
+		}
+		result = count > 1;
+		return result;
+	}
+
+	/**
+	 * This method can be called to determine if the model manager is within a
+	 * "aboutToChange" and "changed" sequence.
+	 * 
+	 * @deprecated the manager does not otherwise interact with these states
+	 * @return false
+	 */
+	public boolean isStateChanging() {
+		// doesn't seem to be used anymore
+		return false;
+	}
+
+	/**
+	 * This method changes the id of the model. TODO: try to refine the design
+	 * not to use this function
+	 */
+	public void moveModel(Object oldId, Object newId) {
+		Assert.isNotNull(oldId, "old id parameter can not be null"); //$NON-NLS-1$
+		Assert.isNotNull(newId, "new id parameter can not be null"); //$NON-NLS-1$
+		SYNC.acquire();
+		SharedObject sharedObject = (SharedObject) fManagedObjects.get(oldId);
+		// if not found in cache, ignore request.
+		// this would normally be a program error
+		if (sharedObject != null) {
+			fManagedObjects.remove(oldId);
+			fManagedObjects.put(newId, sharedObject);
+		}
+		SYNC.release();
+	}
+
+	private String readInputStream(InputStream inputStream, String ianaEncodingName) throws UnsupportedEncodingException, IOException {
+
+		String allText = null;
+		if ((ianaEncodingName != null) && (ianaEncodingName.length() != 0)) {
+			String enc = CodedIO.getAppropriateJavaCharset(ianaEncodingName);
+			if (enc == null) {
+				// if no conversion was possible, let's assume that
+				// the encoding is already a java encoding name, so we'll
+				// proceed with that assumption. This is the case, for
+				// example,
+				// for the reload() procedure.
+				// If in fact it is not a valid java encoding, then
+				// the "allText=" line will cause an
+				// UnsupportedEncodingException
+				enc = ianaEncodingName;
+			}
+			allText = readInputStream(new InputStreamReader(inputStream, enc));
+		}
+		else {
+			// we normally assume encoding is provided for this method, but if
+			// not,
+			// we'll use platform default
+			allText = readInputStream(new InputStreamReader(inputStream));
+		}
+		return allText;
+	}
+
+	private String readInputStream(InputStreamReader inputStream) throws IOException {
+
+		int numRead = 0;
+		StringBuffer buffer = new StringBuffer();
+		char tBuff[] = new char[READ_BUFFER_SIZE];
+		while ((numRead = inputStream.read(tBuff, 0, tBuff.length)) != -1) {
+			buffer.append(tBuff, 0, numRead);
+		}
+		// remember -- we didn't open stream ... so we don't close it
+		return buffer.toString();
+	}
+
+	/*
+	 * @see IModelManager#reinitialize(IStructuredModel)
+	 */
+	public IStructuredModel reinitialize(IStructuredModel model) {
+
+		// getHandler (assume its the "new one")
+		IModelHandler handler = model.getModelHandler();
+		// getLoader for that new one
+		IModelLoader loader = handler.getModelLoader();
+		// ask it to reinitialize
+		model = loader.reinitialize(model);
+		// the loader should check to see if the one it received
+		// is the same type it would normally create.
+		// if not, it must "start from scratch" and create a whole
+		// new one.
+		// if it is of the same type, it should just 'replace text'
+		// replacing all the existing text with the new text.
+		// the important one is the JSP loader ... it should go through
+		// its embedded content checking and initialization
+		return model;
+	}
+
+	 void releaseFromEdit(IStructuredModel structuredModel) {
+		Object id = structuredModel.getId();
+		if (id.equals(UNMANAGED_MODEL) || id.equals(DUPLICATED_MODEL)) {
+			cleanupDiscardedModel(structuredModel);
+		}
+		else {
+			releaseFromEdit(id);
+		}
+
+	}
+	
+	 void releaseFromRead(IStructuredModel structuredModel) {
+		Object id = structuredModel.getId();
+		if (id.equals(UNMANAGED_MODEL) || id.equals(DUPLICATED_MODEL)) {
+			cleanupDiscardedModel(structuredModel);
+		}
+		else {
+			releaseFromRead(id);
+		}
+
+	}
+	/**
+	 * default for use in same package, not subclasses
+	 * 
+	 */
+	 private void releaseFromEdit(Object id) {
+		// ISSUE: many of these asserts should be changed to "logs"
+		// and continue to limp along?
+
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+		SharedObject sharedObject = null;
+
+		// ISSUE: here we need better "spec" what to do with
+		// unmanaged or duplicated models. Release still needs
+		// to be called on them, for now, but the model manager
+		// doesn't need to do anything.
+		if (id.equals(UNMANAGED_MODEL) || id.equals(DUPLICATED_MODEL)) {
+			throw new IllegalArgumentException("Ids of UNMANAGED_MODEL or DUPLICATED_MODEL are illegal here");
+		}
+		else {
+			SYNC.acquire();
+			sharedObject = (SharedObject) fManagedObjects.get(id);
+			SYNC.release();
+			
+			Assert.isNotNull(sharedObject, "release was requested on a model that was not being managed"); //$NON-NLS-1$
+			sharedObject.waitForLoadAttempt();
+			SYNC.acquire();
+			synchronized(sharedObject) {
+				_decrCount(sharedObject, EDIT);
+				if ((sharedObject.referenceCountForRead == 0) && (sharedObject.referenceCountForEdit == 0)) {
+					discardModel(id, sharedObject);
+				}
+			}
+			SYNC.release();
+			// if edit goes to zero, but still open for read,
+			// then we should reload here, so we are in synch with
+			// contents on disk.
+			// ISSUE: should we check isDirty here?
+			// ANSWER: here, for now now. model still has its own dirty
+			// flag for some reason.
+			// we need to address * that * too.
+
+			synchronized(sharedObject) {
+				if ((sharedObject.referenceCountForRead > 0) && (sharedObject.referenceCountForEdit == 0) && sharedObject.theSharedModel.isDirty()) {
+					signalPreLifeCycleListenerRevert(sharedObject.theSharedModel);
+					revertModel(id, sharedObject);
+					/*
+					 * Because model events are fired to notify about the
+					 * revert's changes, and listeners can still get/release
+					 * the model from this thread (locking prevents it being
+					 * done from other threads), the reference counts could
+					 * have changed since we entered this if block, and the
+					 * model could have been discarded.  Check the counts again.
+					 */
+					if (sharedObject.referenceCountForRead > 0 && sharedObject.referenceCountForEdit == 0) {
+						sharedObject.theSharedModel.setDirtyState(false);
+					}
+					signalPostLifeCycleListenerRevert(sharedObject.theSharedModel);
+				}
+			}
+			
+		}
+	}
+
+	// private for now, though public forms have been requested, in past.
+	private void revertModel(Object id, SharedObject sharedObject) {
+		IStructuredDocument structuredDocument = sharedObject.theSharedModel.getStructuredDocument();
+		FileBufferModelManager.getInstance().revert(structuredDocument);
+	}
+
+	private void signalPreLifeCycleListenerRevert(IStructuredModel structuredModel) {
+		int type = ModelLifecycleEvent.MODEL_REVERT | ModelLifecycleEvent.PRE_EVENT;
+		// what's wrong with this design that a cast is needed here!?
+		ModelLifecycleEvent event = new ModelLifecycleEvent(structuredModel, type);
+		((AbstractStructuredModel) structuredModel).signalLifecycleEvent(event);
+	}
+
+	private void signalPostLifeCycleListenerRevert(IStructuredModel structuredModel) {
+		int type = ModelLifecycleEvent.MODEL_REVERT | ModelLifecycleEvent.POST_EVENT;
+		// what's wrong with this design that a cast is needed here!?
+		ModelLifecycleEvent event = new ModelLifecycleEvent(structuredModel, type);
+		((AbstractStructuredModel) structuredModel).signalLifecycleEvent(event);
+	}
+
+	private void discardModel(Object id, SharedObject sharedObject) {
+		SYNC.acquire();
+		fManagedObjects.remove(id);
+		SYNC.release();
+		IStructuredDocument structuredDocument = sharedObject.theSharedModel.getStructuredDocument();
+
+		if (structuredDocument == null) {
+			Platform.getLog(SSECorePlugin.getDefault().getBundle()).log(new Status(IStatus.ERROR, SSECorePlugin.ID, IStatus.ERROR, "Attempted to discard a structured model but the underlying document has already been set to null: " + sharedObject.theSharedModel.getBaseLocation(), null));
+		}
+
+		cleanupDiscardedModel(sharedObject.theSharedModel);
+	}
+
+	private void cleanupDiscardedModel(IStructuredModel structuredModel) {
+		IStructuredDocument structuredDocument = structuredModel.getStructuredDocument();
+		/*
+		 * This call (and setting the StructuredDocument to null) were
+		 * previously done within the model itself, but for concurrency it
+		 * must be done here during a synchronized release.
+		 */
+		structuredModel.getFactoryRegistry().release();
+
+		/*
+		 * For structured documents originating from file buffers, disconnect
+		 * us from the file buffer, now.
+		 */
+		FileBufferModelManager.getInstance().releaseModel(structuredDocument);
+
+		/*
+		 * Setting the document to null is required since some subclasses of
+		 * model might have "cleanup" of listeners, etc., to remove, which
+		 * were initialized during the initial setStructuredDocument.
+		 * 
+		 * The model itself in particular may have internal listeners used to
+		 * coordinate the document with its own "structure".
+		 */
+		structuredModel.setStructuredDocument(null);
+	}
+
+	
+	/**
+	 * default for use in same package, not subclasses
+	 * 
+	 */
+	 private void releaseFromRead(Object id) {
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+		SharedObject sharedObject = null;
+
+		if (id.equals(UNMANAGED_MODEL) || id.equals(DUPLICATED_MODEL)) {
+			throw new IllegalArgumentException("Ids of UNMANAGED_MODEL or DUPLICATED_MODEL are illegal here");
+		}
+		else {
+			SYNC.acquire();
+			sharedObject = (SharedObject) fManagedObjects.get(id);
+			SYNC.release();
+			Assert.isNotNull(sharedObject, "release was requested on a model that was not being managed"); //$NON-NLS-1$
+			sharedObject.waitForLoadAttempt();
+		}
+		SYNC.acquire();
+		synchronized(sharedObject) {
+			_decrCount(sharedObject, READ);
+			if ((sharedObject.referenceCountForRead == 0) && (sharedObject.referenceCountForEdit == 0)) {
+				discardModel(id, sharedObject);
+			}
+		}
+		SYNC.release();
+	}
+
+	/**
+	 * This is similar to the getModel method, except this method does not use
+	 * the cached version, but forces the cached version to be replaced with a
+	 * fresh, unchanged version. Note: this method does not change any
+	 * reference counts. Also, if there is not already a cached version of the
+	 * model, then this call is essentially ignored (that is, it does not put
+	 * a model in the cache) and returns null.
+	 * 
+	 * @deprecated - will become protected, use reload directly on model
+	 */
+	public  IStructuredModel reloadModel(Object id, java.io.InputStream inputStream) throws java.io.UnsupportedEncodingException {
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+
+		// get the existing model associated with this id
+		IStructuredModel structuredModel = getExistingModel(id);
+		// for the model to be null is probably an error (that is,
+		// reload should not have been called, but we'll guard against
+		// a null pointer example and return null if we are no longer managing
+		// that model.
+		if (structuredModel != null) {
+			// get loader based on existing type
+			// dmwTODO evaluate when reload should occur
+			// with potentially new type (e.g. html 'save as' jsp).
+			IModelHandler handler = structuredModel.getModelHandler();
+			IModelLoader loader = handler.getModelLoader();
+			// ask the loader to re-load
+			loader.reload(Utilities.getMarkSupportedStream(inputStream), structuredModel);
+			trace("re-loading model", id); //$NON-NLS-1$
+		}
+		return structuredModel;
+	}
+
+	public void saveModel(IFile iFile, String id, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException {
+		Assert.isNotNull(iFile, "file parameter can not be null"); //$NON-NLS-1$
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+
+		// let's see if we already have it in our cache
+	
+		SYNC.acquire();
+		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
+		if (sharedObject == null || sharedObject.theSharedModel == null) {
+			SYNC.release();
+			throw new IllegalStateException(SSECoreMessages.Program_Error__ModelManage_EXC_); //$NON-NLS-1$ = "Program Error: ModelManagerImpl::saveModel. Model should be in the cache"
+		} 
+		else {
+			SYNC.release();
+			sharedObject.waitForLoadAttempt();
+			
+			/**
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=221610
+			 * 
+			 * Sync removed from here to prevent deadlock. Although the model
+			 * instance may disappear or be made invalid while the save is
+			 * happening, the document itself still has the contents we're
+			 * trying to save. Simultaneous saves should be throttled by
+			 * resource locking without our intervention.
+			 */
+			boolean saved = false;
+			// if this model was based on a File Buffer and we're writing back
+			// to the same location, use the buffer to do the writing
+			if (FileBufferModelManager.getInstance().isExistingBuffer(sharedObject.theSharedModel.getStructuredDocument())) {
+				ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer(sharedObject.theSharedModel.getStructuredDocument());
+				IPath fileLocation = FileBuffers.normalizeLocation(iFile.getFullPath());
+				if (fileLocation.equals(buffer.getLocation())) {
+					buffer.commit(new NullProgressMonitor(), true);
+					saved = true;
+				}
+			}
+			if (!saved) {
+				IStructuredModel model = sharedObject.theSharedModel;
+				IStructuredDocument document = model.getStructuredDocument();
+				saveStructuredDocument(document, iFile, encodingRule);
+				trace("saving model", id); //$NON-NLS-1$
+			}
+			sharedObject.theSharedModel.setDirtyState(false);
+			sharedObject.theSharedModel.setNewState(false);
+		}	
+	}
+
+	/**
+	 * Saving the model really just means to save it's structured document.
+	 * 
+	 * @param id
+	 * @param outputStream
+	 * @param encodingRule
+	 * @throws UnsupportedEncodingException
+	 * @throws IOException
+	 * @throws CoreException
+	 */
+	public void saveModel(String id, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException {
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+
+		// let's see if we already have it in our cache
+
+		SYNC.acquire();
+		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
+		if (sharedObject == null) {
+			SYNC.release();
+			throw new IllegalStateException(SSECoreMessages.Program_Error__ModelManage_EXC_); //$NON-NLS-1$ = "Program Error: ModelManagerImpl::saveModel. Model should be in the cache"
+		}
+		else {
+			SYNC.release();
+			sharedObject.waitForLoadAttempt();
+			/**
+			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=221610
+			 * 
+			 * Sync removed from here to prevent deadlock. Although the model
+			 * instance may disappear or be made invalid while the save is
+			 * happening, the document itself still has the contents we're
+			 * trying to save. Simultaneous saves should be throttled by
+			 * resource locking without our intervention.
+			 */
+			/*
+			 * if this model was based on a File Buffer and we're writing back
+			 * to the same location, use the buffer to do the writing
+			 */
+			if (FileBufferModelManager.getInstance().isExistingBuffer(sharedObject.theSharedModel.getStructuredDocument())) {
+				ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer(sharedObject.theSharedModel.getStructuredDocument());
+				buffer.commit(new NullProgressMonitor(), true);
+			}
+			else {
+				IFile iFile = getFileFor(sharedObject.theSharedModel);
+				IStructuredModel model = sharedObject.theSharedModel;
+				IStructuredDocument document = model.getStructuredDocument();
+				saveStructuredDocument(document, iFile);
+				trace("saving model", id); //$NON-NLS-1$
+			}
+			sharedObject.theSharedModel.setDirtyState(false);
+			sharedObject.theSharedModel.setNewState(false);
+		}
+	}
+
+	/**
+	 * @deprecated - this method is less efficient than IFile form, since it
+	 *             requires an extra "copy" of byte array, and should be avoid
+	 *             in favor of the IFile form.
+	 */
+	public void saveModel(String id, OutputStream outputStream, EncodingRule encodingRule) throws UnsupportedEncodingException, CoreException, IOException {
+		Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$
+
+		SYNC.acquire();
+		// let's see if we already have it in our cache
+		SharedObject sharedObject = (SharedObject) fManagedObjects.get(id);
+		if (sharedObject == null) {
+			SYNC.release();
+			throw new IllegalStateException(SSECoreMessages.Program_Error__ModelManage_EXC_); //$NON-NLS-1$ = "Program Error: ModelManagerImpl::saveModel. Model should be in the cache"
+		}
+		else {
+			SYNC.release();
+			sharedObject.waitForLoadAttempt();
+			synchronized(sharedObject) {
+				CodedStreamCreator codedStreamCreator = new CodedStreamCreator();
+				codedStreamCreator.set(sharedObject.theSharedModel.getId(), new DocumentReader(sharedObject.theSharedModel.getStructuredDocument()));
+				codedStreamCreator.setPreviousEncodingMemento(sharedObject.theSharedModel.getStructuredDocument().getEncodingMemento());
+				ByteArrayOutputStream byteArrayOutputStream = codedStreamCreator.getCodedByteArrayOutputStream(encodingRule);
+				byte[] outputBytes = byteArrayOutputStream.toByteArray();
+				outputStream.write(outputBytes);
+				trace("saving model", id); //$NON-NLS-1$
+				sharedObject.theSharedModel.setDirtyState(false);
+				sharedObject.theSharedModel.setNewState(false);
+			}
+		}
+	}
+
+	public void saveStructuredDocument(IStructuredDocument structuredDocument, IFile iFile) throws UnsupportedEncodingException, CoreException, IOException {
+		saveStructuredDocument(structuredDocument, iFile, EncodingRule.CONTENT_BASED);
+	}
+
+	public void saveStructuredDocument(IStructuredDocument structuredDocument, IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, CoreException, IOException {
+		Assert.isNotNull(iFile, "file parameter can not be null"); //$NON-NLS-1$
+		if (FileBufferModelManager.getInstance().isExistingBuffer(structuredDocument)) {
+			ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer(structuredDocument);
+			if (buffer.getLocation().equals(iFile.getFullPath()) || buffer.getLocation().equals(iFile.getLocation())) {
+				buffer.commit(new NullProgressMonitor(), true);
+			}
+		}
+		else {
+			// IModelHandler handler = calculateType(iFile);
+			// IDocumentDumper dumper = handler.getDocumentDumper();
+			CodedStreamCreator codedStreamCreator = new CodedStreamCreator();
+			Reader reader = new DocumentReader(structuredDocument);
+			codedStreamCreator.set(iFile, reader);
+			codedStreamCreator.setPreviousEncodingMemento(structuredDocument.getEncodingMemento());
+			EncodingMemento encodingMemento = codedStreamCreator.getCurrentEncodingMemento();
+
+			// be sure document's is updated, in case exception is thrown in
+			// getCodedByteArrayOutputStream
+			structuredDocument.setEncodingMemento(encodingMemento);
+
+			// Convert line delimiters after encoding memento is figured out,
+			// but
+			// before writing to output stream.
+			handleConvertLineDelimiters(structuredDocument, iFile, encodingRule, encodingMemento);
+
+			ByteArrayOutputStream codedByteStream = codedStreamCreator.getCodedByteArrayOutputStream(encodingRule);
+			InputStream codedStream = new ByteArrayInputStream(codedByteStream.toByteArray());
+			if (iFile.exists())
+				iFile.setContents(codedStream, true, true, null);
+			else
+				iFile.create(codedStream, false, null);
+			codedByteStream.close();
+			codedStream.close();
+		}
+	}
+
+	/**
+	 * Common trace method
+	 */
+	private void trace(String msg, Object id) {
+		if (Logger.DEBUG_MODELMANAGER) {
+			Logger.log(Logger.INFO, msg + " " + Utilities.makeShortId(id)); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+	}
+
+	/**
+	 * Common trace method
+	 */
+	private void trace(String msg, Object id, int value) {
+		if (Logger.DEBUG_MODELMANAGER) {
+			Logger.log(Logger.INFO, msg + Utilities.makeShortId(id) + " (" + value + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		}
+	}
+
+	 boolean isIdInUse(String newId) {
+			boolean inUse = false;
+			SYNC.acquire();
+			SharedObject object =(SharedObject) fManagedObjects.get(newId);
+			if (object!=null) {
+				inUse = object.theSharedModel!=null;
+			}
+			SYNC.release();
+			return inUse;
+		}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/PrefUtil.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/PrefUtil.java
new file mode 100644
index 0000000..ee29ad3
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/PrefUtil.java
@@ -0,0 +1,146 @@
+/*******************************************************************************

+ * Copyright (c) 2010 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.wst.sse.core.internal.model;

+

+import org.eclipse.core.runtime.Platform;

+import org.eclipse.core.runtime.preferences.ConfigurationScope;

+import org.eclipse.core.runtime.preferences.IEclipsePreferences;

+import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;

+import org.eclipse.core.runtime.preferences.IPreferencesService;

+import org.eclipse.core.runtime.preferences.InstanceScope;

+import org.eclipse.osgi.util.NLS;

+import org.eclipse.wst.sse.core.internal.SSECorePlugin;

+import org.osgi.service.prefs.Preferences;

+

+class PrefUtil {

+

+	static long WAIT_INTERVAL_MS = 500;

+	static int WAIT_DELAY = getInt("org.eclipse.wst.sse.core.modelmanager.maxWaitDuringConcurrentLoad");

+	static boolean ALLOW_INTERRUPT_WAITING_THREAD = getBoolean("org.eclipse.wst.sse.core.modelmanager.allowInterruptsDuringConcurrentLoad");

+

+	/** Base of millisecond timings, to avoid wrapping */

+	private static final long MILLI_ORIGIN = System.currentTimeMillis();

+

+	/**

+	 * Returns millisecond time offset by origin

+	 */

+	static final long now() {

+		return System.currentTimeMillis() - MILLI_ORIGIN;

+	}

+	

+	private static IEclipsePreferences.IPreferenceChangeListener LISTENER;

+	static {

+		InstanceScope scope = new InstanceScope();

+		IEclipsePreferences instancePrefs = scope.getNode(SSECorePlugin.ID);

+		LISTENER = new IEclipsePreferences.IPreferenceChangeListener() {

+

+			public void preferenceChange(PreferenceChangeEvent event) {

+

+				if ("modelmanager.maxWaitDuringConcurrentLoad".equals(event.getKey())) {

+					WAIT_DELAY = getInt("org.eclipse.wst.sse.core.modelmanager.maxWaitDuringConcurrentLoad");

+				}

+				else if ("modelmanager.allowInterruptsDuringConcurrentLoad".equals(event.getKey())) {

+					ALLOW_INTERRUPT_WAITING_THREAD = getBoolean("org.eclipse.wst.sse.core.modelmanager.allowInterruptsDuringConcurrentLoad");

+				}

+			}

+		};

+		instancePrefs.addPreferenceChangeListener(LISTENER);

+	}

+

+	private static String getProperty(String property) {

+		// Importance order is:

+		// default-default < instanceScope < configurationScope < systemProperty

+		// < envVar

+		String value = null;

+

+		if (value == null) {

+			value = System.getenv(property);

+		}

+		if (value == null) {

+			value = System.getProperty(property);

+		}

+		if (value == null) {

+			IPreferencesService preferencesService = Platform.getPreferencesService();

+			

+			String key = property;

+			if (property != null && property.startsWith(SSECorePlugin.ID)) {

+				// +1, include the "."

+				key = property.substring(SSECorePlugin.ID.length() + 1, property.length());

+			}

+			InstanceScope instance = new InstanceScope();

+			ConfigurationScope config = new ConfigurationScope();

+			

+			Preferences instanceNode = instance.getNode(SSECorePlugin.ID);

+			Preferences configNode = config.getNode(SSECorePlugin.ID);

+			value = preferencesService.get(key, getDefault(property), new Preferences[]{configNode,instanceNode});

+		}

+

+		return value;

+	}

+

+	private static String getDefault(String property) {

+		// this is the "default-default"

+		if ("org.eclipse.wst.sse.core.modelmanager.maxWaitDuringConcurrentLoad".equals(property)) {

+			return "0";

+		}

+		else if ("org.eclipse.wst.sse.core.modelmanager.allowInterruptsDuringConcurrentLoad".equals(property)) {

+			return "false";

+		}

+		return null;

+	}

+

+	private static boolean getBoolean(String key) {

+		String property = getProperty(key);

+		// if (property != null) {

+		//			System.out.println("Tweak: " + key + "=" + Boolean.parseBoolean(property)); //$NON-NLS-1$ //$NON-NLS-2$

+		// }

+		return (property != null ? Boolean.valueOf(property) : Boolean.valueOf(getDefault(key)))

+				.booleanValue();

+	}

+

+	private static int getInt(String key) {

+		String property = getProperty(key);

+		int size = 0;

+		if (property != null) {

+			try {

+				size = Integer.parseInt(property);

+				//	System.out.println("Tweak: " + key + "=" + size); //$NON-NLS-1$ //$NON-NLS-2$

+			}

+			catch (NumberFormatException e) {

+				size = getDefaultInt(key, property, size);

+			}

+		}

+		else {

+			size = getDefaultInt(key, property, size);

+		}

+		return size;

+	}

+

+	private static int getDefaultInt(String key, String property, int size) {

+		// ignored

+		try {

+			size = Integer.parseInt(getDefault(key));

+		}

+		catch (NumberFormatException e1) {

+			handleIntParseException(key, property, e1);

+			size = 0;

+		}

+		return size;

+	}

+

+	private static void handleIntParseException(String key, String property, NumberFormatException e1) {

+		Exception n = new Exception(NLS.bind(

+				"Exception during parse of default value for key ''{0}'' value was ''{1}''. Using 0 instead", //$NON-NLS-1$

+				key, property), e1);

+		n.printStackTrace();

+	}

+}

diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/EmbeddedTypeRegistry.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/EmbeddedTypeRegistry.java
new file mode 100644
index 0000000..60a10a8
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/EmbeddedTypeRegistry.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.modelhandler;
+
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;
+
+/**
+ * The entries in this registry are, conceptually, singleton's Since only one
+ * instance is created in the registry, and then that instance returned when
+ * required.
+ * 
+ * Note that there is intentionally no 'remove' method, Since the registry
+ * itself is read it when once, from the platform's plugin registry, and is
+ * not intended to be modified after that. A change in an extenstion in a
+ * plugin.xml will only take effect when the workbench is re-started.
+ *  
+ */
+public interface EmbeddedTypeRegistry {
+
+	/**
+	 * Method to return the specific type for the specific mimetype.
+	 */
+	public EmbeddedTypeHandler getTypeFor(String mimeType);
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/EmbeddedTypeRegistryImpl.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/EmbeddedTypeRegistryImpl.java
new file mode 100644
index 0000000..8aa890f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/EmbeddedTypeRegistryImpl.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.modelhandler;
+
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IDocumentTypeHandler;
+
+
+/**
+ *  
+ */
+public class EmbeddedTypeRegistryImpl implements EmbeddedTypeRegistry {
+
+	private static EmbeddedTypeRegistry instance = null;
+
+	public synchronized static EmbeddedTypeRegistry getInstance() {
+		if (instance == null) {
+			instance = new EmbeddedTypeRegistryImpl();
+		}
+		return instance;
+	}
+
+	private HashSet hashSet = null;
+	private EmbeddedTypeHandler registryDefaultHandler = null;
+
+	/*
+	 * @see ContentTypeRegistry#getTypeFor(String)
+	 */
+	/**
+	 * Constructor for ContentTypeRegistryImpl.
+	 */
+	private EmbeddedTypeRegistryImpl() {
+		super();
+		hashSet = new HashSet();
+		new EmbeddedTypeRegistryReader().readRegistry(hashSet);
+	}
+
+	/**
+	 * @see ContentTypeRegistry#add(ContentTypeDescription)
+	 */
+	void add(IDocumentTypeHandler contentTypeDescription) {
+		hashSet.add(contentTypeDescription);
+	}
+
+	private EmbeddedTypeHandler getJSPDefaultEmbeddedType() {
+		return getTypeFor("text/html"); //$NON-NLS-1$
+	}
+
+	/**
+	 * Method getRegistryDefault. We cache the default handler, since can't
+	 * change once plugin descriptors are loaded.
+	 * 
+	 * @return EmbeddedTypeHandler
+	 */
+	private EmbeddedTypeHandler getRegistryDefault() {
+		if (registryDefaultHandler == null) {
+			Iterator it = hashSet.iterator();
+			while ((registryDefaultHandler == null) && (it.hasNext())) { // safe
+				// cast
+				// since
+				// 'add'
+				// requires
+				// EmbeddedContentTypeDescription
+				EmbeddedTypeHandler item = (EmbeddedTypeHandler) it.next();
+				if ((item != null) && (item.isDefault())) {
+					registryDefaultHandler = item;
+					break;
+				}
+			}
+		}
+		return registryDefaultHandler;
+	}
+
+	/**
+	 * Finds the contentTypeDescription based on literal id. Its basically a
+	 * "first found first returned". Note the order is fairly unpredictable,
+	 * so non-unique ids would cause problems.
+	 */
+	public EmbeddedTypeHandler getTypeFor(String mimeType) {
+		// Note: the reason we have this precondition is that the
+		// default is different inside the registry than when called,
+		// for example, from the JSPLoader. For the JSPLoader, if there
+		// is no mimetype, the default should be HTML. Here, if there is
+		// some mimetype, but it is not recognized, we return a default
+		// for XML. This is required for various voice xml types, etc.
+		EmbeddedTypeHandler found = null;
+		if (mimeType == null || mimeType.trim().length() == 0) {
+			found = getJSPDefaultEmbeddedType();
+		} else {
+			Iterator it = hashSet.iterator();
+			while ((found == null) && (it.hasNext())) { // safe cast since
+				// 'add' requires
+				// EmbeddedContentTypeDescription
+				EmbeddedTypeHandler item = (EmbeddedTypeHandler) it.next();
+				if ((item != null) && (item.getSupportedMimeTypes().contains(mimeType))) {
+					found = item;
+					break;
+				}
+			}
+			// if no exact match, do the "looser" check
+			if(found == null) {
+				it = hashSet.iterator();
+				while ((found == null) && (it.hasNext())) { 
+					EmbeddedTypeHandler item = (EmbeddedTypeHandler) it.next();
+					if ((item != null) && (item.canHandleMimeType(mimeType))) {
+						found = item;
+						break;
+					}
+				}
+			}
+		}
+		// no matches, use default
+		if (found == null) {
+			found = getRegistryDefault();
+		}
+		return found;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/EmbeddedTypeRegistryReader.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/EmbeddedTypeRegistryReader.java
new file mode 100644
index 0000000..698f7a1
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/EmbeddedTypeRegistryReader.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.modelhandler;
+
+import java.util.Set;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+
+
+public class EmbeddedTypeRegistryReader {
+	protected String ATT_CLASS = "class"; //$NON-NLS-1$
+	protected String EXTENSION_POINT_ID = "embeddedTypeHandler"; //$NON-NLS-1$
+
+
+	protected String PLUGIN_ID = "org.eclipse.wst.sse.core"; //$NON-NLS-1$
+	protected String TAG_NAME = "embeddedTypeHandler"; //$NON-NLS-1$
+
+	EmbeddedTypeRegistryReader() {
+		super();
+	}
+
+	protected EmbeddedTypeHandler readElement(IConfigurationElement element) {
+
+		EmbeddedTypeHandler contentTypeDescription = null;
+		if (element.getName().equals(TAG_NAME)) {
+			try {
+				contentTypeDescription = (EmbeddedTypeHandler) element.createExecutableExtension(ATT_CLASS);
+			} catch (Exception e) {
+				Logger.logException(e);
+			}
+		}
+		Assert.isNotNull(contentTypeDescription, "Error reading content type description"); //$NON-NLS-1$
+		return contentTypeDescription;
+	}
+
+	/**
+	 * We simply require an 'add' method, of what ever it is we are to read
+	 * into
+	 */
+	void readRegistry(Set set) {
+		IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
+		IExtensionPoint point = extensionRegistry.getExtensionPoint(PLUGIN_ID, EXTENSION_POINT_ID);
+		if (point != null) {
+			IConfigurationElement[] elements = point.getConfigurationElements();
+			for (int i = 0; i < elements.length; i++) {
+				EmbeddedTypeHandler embeddedContentType = readElement(elements[i]);
+				// null can be returned if there's an error reading the
+				// element
+				if (embeddedContentType != null) {
+					set.add(embeddedContentType);
+				}
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/ModelHandlerRegistry.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/ModelHandlerRegistry.java
new file mode 100644
index 0000000..72bfa13
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/ModelHandlerRegistry.java
@@ -0,0 +1,311 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.modelhandler;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+
+
+public class ModelHandlerRegistry {
+	private static ModelHandlerRegistry instance = null;
+	static final String INTERNAL_DEFAULT_EXTENSION = "org.eclipse.wst.xml.core.internal.modelhandler"; //$NON-NLS-1$
+
+	public synchronized static ModelHandlerRegistry getInstance() {
+		if (instance == null) {
+			instance = new ModelHandlerRegistry();
+		}
+		return instance;
+	}
+
+	private IModelHandler defaultHandler = null;
+	private ModelHandlerRegistryReader reader = new ModelHandlerRegistryReader();
+
+	private ModelHandlerRegistry() {
+		super();
+		reader = new ModelHandlerRegistryReader().readRegistry();
+	}
+
+	/**
+	 * Finds the default model handler. Note: we still go through the registry
+	 * to be sure to get the existing instance, but then we do remember it, so
+	 * subsequent requests will be faster. The first time through, we do check
+	 * the whole list, to be sure there is only one.
+	 * 
+	 */
+	final public IModelHandler getDefault() {
+		if (defaultHandler == null) {
+			IConfigurationElement[] elements = reader.elements;
+			for (int i = 0; i < elements.length; i++) {
+				boolean ofInterest = reader.isElementDefault(elements[i]);
+				if (ofInterest) {
+					/*
+					 * If, here within the search loop we've already found one
+					 * defaultHandler, then something is wrong!
+					 */
+					if (defaultHandler == null) {
+						defaultHandler = reader.getInstance(elements[i]);
+					}
+					else {
+						String errorString = "Program or configuration error. More than one default content handler found"; //$NON-NLS-1$
+						Logger.log(Logger.ERROR, errorString);
+						throw new IllegalStateException(errorString);
+					}
+				}
+			}
+		}
+		if (defaultHandler == null) {
+			String errorString = "Program or configuration error. No default content type handler found."; //$NON-NLS-1$
+			Logger.log(Logger.ERROR, errorString);
+			throw new IllegalStateException(errorString);
+		}
+		return defaultHandler;
+	}
+
+	/**
+	 * Finds a ModelHandler based on literal extension id. It's basically a
+	 * "first found first returned". No specific order is guaranteed and the
+	 * uniqueness of IDs is not considered.
+	 * 
+	 * @param extensionId
+	 * @return the given extension, or null
+	 */
+	private IModelHandler getHandlerExtension(String extensionId) {
+		IModelHandler found = null;
+		IConfigurationElement[] elements = reader.elements;
+		if (elements != null) {
+			for (int i = 0; i < elements.length; i++) {
+				String currentId = reader.getId(elements[i]);
+				if (extensionId.equals(currentId)) {
+					IModelHandler item = reader.getInstance(elements[i]);
+					found = item;
+				}
+			}
+		}
+		else if (Logger.DEBUG){
+			Logger.log(Logger.WARNING, "There were no Model Handler found in registry"); //$NON-NLS-1$
+		}
+		return found;
+	}
+
+	/**
+	 * Finds the registered IModelHandler for a given named file's content
+	 * type.
+	 * 
+	 * @param file
+	 * @param provideDefault should the default extension be used in the absence of other methods
+	 * @return The IModelHandler registered for the content type of the given
+	 *         file. If an exact match is not found, the most-specific match
+	 *         according to IContentType.isKindOf() will be returned. If none
+	 *         are found, either a default or null will be returned.
+	 * @throws CoreException
+	 */
+	public IModelHandler getHandlerFor(IFile file, boolean provideDefault) throws CoreException {
+		IModelHandler modelHandler = null;
+		IContentDescription contentDescription = null;
+		IContentType contentType = null;
+		boolean accessible = file.isAccessible();
+		if (accessible) {
+			/* Try the optimized method first as the description may be cached */
+			contentDescription = file.getContentDescription();
+			if (contentDescription != null) {
+				// use the provided description
+				contentType = contentDescription.getContentType();
+			}
+			else {
+				/* use the more thorough discovery method to get a description */
+				InputStream contents = null;
+				try {
+					contents = file.getContents(false);
+					contentDescription = Platform.getContentTypeManager().getDescriptionFor(contents, file.getName(), IContentDescription.ALL);
+					if (contentDescription != null) {
+						contentType = contentDescription.getContentType();
+					}
+				}
+				catch (IOException e) {
+					// nothing further can be done, but will log for debugging
+					Logger.logException(e);
+				}
+				finally {
+					if (contents != null) {
+						try {
+							contents.close();
+						}
+						catch (IOException e1) {
+							// nothing can be done
+						}
+					}
+				}
+			}
+		}
+
+		/*
+		 * If we couldn't get the content type from a description, try basing
+		 * it on just the filename
+		 */
+		if (contentType == null) {
+			contentType = Platform.getContentTypeManager().findContentTypeFor(file.getName());
+		}
+
+		if (contentType != null) {
+			modelHandler = getHandlerForContentType(contentType);
+		}
+		else if (contentType == null && provideDefault) {
+			// hard coding for null content type
+			modelHandler = getHandlerExtension(INTERNAL_DEFAULT_EXTENSION); //$NON-NLS-1$
+		}
+
+		return modelHandler;
+	}
+
+	/**
+	 * Finds the registered IModelHandler for a given named file's content
+	 * type. Will check for a default.
+	 * 
+	 * @param file
+	 * @return The IModelHandler registered for the content type of the given
+	 *         file. If an exact match is not found, the most-specific match
+	 *         according to IContentType.isKindOf() will be returned. If none
+	 *         are found, either a default or null will be returned.
+	 * @throws CoreException
+	 */
+	public IModelHandler getHandlerFor(IFile file) throws CoreException {
+		return getHandlerFor(file, true);
+	}
+
+
+	/**
+	 * Finds the registered IModelHandler for a given named InputStream.
+	 * 
+	 * @param inputName
+	 * @param inputStream
+	 * @return The IModelHandler registered for the content type of the given
+	 *         input. If an exact match is not found, the most-specific match
+	 *         according to IContentType.isKindOf() will be returned. If none
+	 *         are found, either a default or null will be returned.
+	 * @throws IOException
+	 */
+	public IModelHandler getHandlerFor(String inputName, InputStream inputStream) throws IOException {
+		InputStream iStream = Utilities.getMarkSupportedStream(inputStream);
+		IModelHandler modelHandler = null;
+		IContentType contentType = null;
+		if (inputStream != null) {
+			try {
+				iStream.mark(CodedIO.MAX_MARK_SIZE);
+				contentType = Platform.getContentTypeManager().findContentTypeFor(Utilities.getLimitedStream(iStream), inputName);
+			}
+			finally {
+				if (iStream != null && iStream.markSupported()) {
+					iStream.reset();
+				}
+			}
+
+		}
+		if (contentType == null) {
+			contentType = Platform.getContentTypeManager().findContentTypeFor(inputName);
+		}
+		// if all else failed, try to detect solely on contents; done last for
+		// performance reasons
+		if (contentType == null) {
+			contentType = Platform.getContentTypeManager().findContentTypeFor(Utilities.getLimitedStream(iStream), null);
+		}
+		modelHandler = getHandlerForContentType(contentType);
+		return modelHandler;
+	}
+
+	/**
+	 * Finds the registered IModelHandler for a given IContentType.
+	 * 
+	 * @param contentType
+	 * @return The IModelHandler registered for the given content type. If an
+	 *         exact match is not found, the most-specific match according to
+	 *         IContentType.isKindOf() will be returned. If none are found,
+	 *         either a default or null will be returned.
+	 */
+	private IModelHandler getHandlerForContentType(IContentType contentType) {
+		IModelHandler handler = null;
+		if (contentType != null) {
+			IConfigurationElement exactContentTypeElement = null;
+			IConfigurationElement kindOfContentTypeElement = null;
+			int kindOfContentTypeDepth = 0;
+			IConfigurationElement[] elements = reader.elements;
+			if (elements != null) {
+				for (int i = 0; i < elements.length && exactContentTypeElement == null; i++) {
+					String currentId = reader.getAssociatedContentTypeId(elements[i]);
+					IContentType associatedContentType = Platform.getContentTypeManager().getContentType(currentId);
+					if (contentType.equals(associatedContentType)) {
+						exactContentTypeElement = elements[i];
+					}
+					else if (contentType.isKindOf(associatedContentType)) {
+						/*
+						 * Update the kindOfElement variable only if this
+						 * element's content type is "deeper" (depth test
+						 * ensures the first content type is remembered)
+						 */
+						IContentType testContentType = associatedContentType;
+						int testDepth = 0;
+						while (testContentType != null) {
+							testDepth++;
+							testContentType = testContentType.getBaseType();
+						}
+						if (testDepth > kindOfContentTypeDepth) {
+							kindOfContentTypeElement = elements[i];
+							kindOfContentTypeDepth = testDepth;
+						}
+					}
+				}
+			}
+			else if (Logger.DEBUG){
+				Logger.log(Logger.WARNING, "There were no Model Handler found in registry"); //$NON-NLS-1$
+			}
+			if (exactContentTypeElement != null) {
+				handler = reader.getInstance(exactContentTypeElement);
+			}
+			else if (kindOfContentTypeElement != null) {
+				handler = reader.getInstance(kindOfContentTypeElement);
+			}
+		}
+
+		if (handler == null) {
+			// temp hard coding for null content type arguments
+			handler = getHandlerExtension(INTERNAL_DEFAULT_EXTENSION); //$NON-NLS-1$
+		}
+		return handler;
+	}
+
+	/**
+	 * Finds the registered IModelHandler for a given content type ID. No
+	 * specific order is guaranteed and the uniqueness of IDs is not
+	 * considered.
+	 * 
+	 * @param contentType
+	 * @return The IModelHandler registered for the given content type ID. If
+	 *         an exact match is not found, the most-specific match according
+	 *         to IContentType.isKindOf() will be returned. If none are found,
+	 *         either a default or null will be returned.
+	 */
+	public IModelHandler getHandlerForContentTypeId(String contentTypeId) {
+		IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeId);
+		return getHandlerForContentType(contentType);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/ModelHandlerRegistryReader.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/ModelHandlerRegistryReader.java
new file mode 100644
index 0000000..c6d611f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/ModelHandlerRegistryReader.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.modelhandler;
+
+import java.util.HashMap;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.AbstractModelHandler;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+
+
+/**
+ * This class just converts what's in the plugins registry into a form more
+ * easily useable by others, the ContentTypeRegistry.
+ */
+class ModelHandlerRegistryReader {
+	private HashMap allReadyCreateInstances = new HashMap();
+	protected String ATT_ASSOCIATED_CONTENT_TYPE = "associatedContentTypeId"; //$NON-NLS-1$
+	protected String ATT_CLASS = "class"; //$NON-NLS-1$
+	protected String ATT_DEFAULT = "default"; //$NON-NLS-1$
+	protected String ATT_ID = "id"; //$NON-NLS-1$
+	IConfigurationElement[] elements;
+	protected String EXTENSION_POINT_ID = "modelHandler"; //$NON-NLS-1$
+	//
+	protected String PLUGIN_ID = "org.eclipse.wst.sse.core"; //$NON-NLS-1$
+	protected String TAG_NAME = "modelHandler"; //$NON-NLS-1$
+
+	//
+	/**
+	 * ContentTypeRegistryReader constructor comment.
+	 */
+	ModelHandlerRegistryReader() {
+		super();
+	}
+
+	String getAssociatedContentTypeId(IConfigurationElement element) {
+		String value = element.getAttribute(ATT_ASSOCIATED_CONTENT_TYPE);
+		return value;
+	}
+
+	String getId(IConfigurationElement element) {
+		String idValue = element.getAttribute(ATT_ID);
+		return idValue;
+	}
+
+	synchronized IModelHandler getInstance(IConfigurationElement element) {
+		// May need to reconsider, but for now, we'll assume all clients must
+		// subclass AbstractContentTypeIdentifier. Its easier and safer, for
+		// this
+		// low level "system" object. (That is, we can check and set "package
+		// protected"
+		// attributes.
+		AbstractModelHandler modelHandler = (AbstractModelHandler) allReadyCreateInstances.get(getId(element));
+		if (modelHandler == null) {
+			try {
+				modelHandler = (AbstractModelHandler) element.createExecutableExtension(ATT_CLASS);
+				if (modelHandler != null) {
+					allReadyCreateInstances.put(getId(element), modelHandler);
+					String defaultValue = element.getAttribute(ATT_DEFAULT);
+					if (defaultValue != null && "true".equals(defaultValue)) //$NON-NLS-1$
+						modelHandler.setDefault(true);
+					else
+						modelHandler.setDefault(false);
+					// TODO -- set and check attributes vs. created instance
+					//contentTypeIdentifier.setOrCheckId(element.getAttribute(ATT_ID));
+				}
+			} catch (CoreException e) {
+				org.eclipse.wst.sse.core.internal.Logger.logException(e);
+			}
+		}
+		return modelHandler;
+	}
+
+	public boolean isElementDefault(IConfigurationElement element) {
+		String defaultValue = element.getAttribute(ATT_DEFAULT);
+		if (defaultValue != null && "true".equals(defaultValue)) //$NON-NLS-1$
+			return true;
+		else
+			return false;
+	}
+
+	ModelHandlerRegistryReader readRegistry() {
+		IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
+		IExtensionPoint point = extensionRegistry.getExtensionPoint(PLUGIN_ID, EXTENSION_POINT_ID);
+		if (point != null) {
+			// just remember the elements, so plugins don't have to
+			// be activated, unless extension matches those "of interest".
+			elements = point.getConfigurationElements();
+		}
+		return this;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/ModelHandlerUtility.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/ModelHandlerUtility.java
new file mode 100644
index 0000000..f0b2a4b
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/ModelHandlerUtility.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.modelhandler;
+
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IDocumentTypeHandler;
+
+/**
+ * 
+ * Likely a temporary class to be replaced by plugin, eventually.
+ */
+public class ModelHandlerUtility {
+
+	private static ModelHandlerRegistry contentTypeRegistry;
+
+	public static IDocumentTypeHandler getContentTypeFor(String string) {
+		return getContentTypeRegistry().getHandlerForContentTypeId(string);
+	}
+
+	private static ModelHandlerRegistry getContentTypeRegistry() {
+		if (contentTypeRegistry == null) {
+			contentTypeRegistry = ModelHandlerRegistry.getInstance();
+		}
+		return contentTypeRegistry;
+	}
+
+	public static EmbeddedTypeHandler getDefaultEmbeddedType() {
+		return getEmbeddedContentTypeFor("text/html"); //$NON-NLS-1$
+	}
+
+	public static EmbeddedTypeHandler getEmbeddedContentTypeFor(String string) {
+		EmbeddedTypeHandler instance = null;
+		instance = EmbeddedTypeRegistryImpl.getInstance().getTypeFor(string);
+		return instance;
+	}
+
+	public ModelHandlerUtility() {
+		super();
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/PluginContributedFactoryReader.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/PluginContributedFactoryReader.java
new file mode 100644
index 0000000..7d2e2dd
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/modelhandler/PluginContributedFactoryReader.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.modelhandler;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.sse.core.internal.SSECorePlugin;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IDocumentTypeHandler;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+
+
+/**
+ * 
+ * Clients can make use of IExecutableExtension to handle the optional adapter
+ * class and key. Typically, many clients use a typical pattern of providing
+ * an adapter class and key in their null argument constructor anyway, so
+ * they'd only have to use IExecutableExtension if the factory was for more
+ * than one.
+ */
+public class PluginContributedFactoryReader {
+	//	protected final String ATTR_ADAPTERKEY = "adapterKeyClass";
+	// //$NON-NLS-1$
+	//	protected final String ATTR_REGISTERADAPTER = "registerAdapters";
+	// //$NON-NLS-1$
+	private static PluginContributedFactoryReader reader = null;
+
+	public synchronized static PluginContributedFactoryReader getInstance() {
+		if (reader == null) {
+			reader = new PluginContributedFactoryReader();
+		}
+		return reader;
+	}
+
+	protected final String ATTR_CLASS = "class"; //$NON-NLS-1$
+	protected final String ATTR_CONTENTTYPE = "contentTypeIdentiferId"; //$NON-NLS-1$
+
+	protected final String EXTENSION_POINT_ID = "contentTypeFactoryContribution"; //$NON-NLS-1$
+	protected final String TAG_NAME = "factory"; //$NON-NLS-1$
+
+	protected PluginContributedFactoryReader() {
+		super();
+	}
+
+	public List getFactories(IDocumentTypeHandler handler) {
+		return loadRegistry(handler.getId());
+	}
+
+	public List getFactories(String type) {
+		return loadRegistry(type);
+	}
+
+	protected INodeAdapterFactory loadFactoryFromConfigurationElement(IConfigurationElement element, Object requesterType) {
+		INodeAdapterFactory factory = null;
+		if (element.getName().equals(TAG_NAME)) {
+			String contentType = element.getAttribute(ATTR_CONTENTTYPE);
+			if (!requesterType.equals(contentType))
+				return null;
+			String className = element.getAttribute(ATTR_CLASS);
+			//			String adapterKeyClass = element.getAttribute(ATTR_ADAPTERKEY);
+			//			String registerAdapters =
+			// element.getAttribute(ATTR_REGISTERADAPTER);
+
+			// if className is null, then no one defined the extension point
+			// for adapter factories
+			if (className != null) {
+				try {
+					factory = (INodeAdapterFactory) element.createExecutableExtension(ATTR_CLASS);
+				} catch (CoreException e) {
+					// if an error occurs here, its probably that the plugin
+					// could not be found/loaded
+					org.eclipse.wst.sse.core.internal.Logger.logException("Could not find class: " + className, e); //$NON-NLS-1$
+				} catch (Exception e) {
+					// if an error occurs here, its probably that the plugin
+					// could not be found/loaded -- but in any case we just
+					// want
+					// to log the error and continue running and best we can.
+					org.eclipse.wst.sse.core.internal.Logger.logException("Could not find class: " + className, e); //$NON-NLS-1$
+				}
+				//				if (plugin != null) {
+				//					factory = oldAttributesCode(element, factory, className,
+				// plugin);
+				//
+			}
+		}
+
+		return factory;
+	}
+
+	protected List loadRegistry(Object contentType) {
+		List factoryList = null; // new Vector();
+		IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
+		IExtensionPoint point = extensionRegistry.getExtensionPoint(SSECorePlugin.ID, EXTENSION_POINT_ID);
+		if (point != null) {
+			IConfigurationElement[] elements = point.getConfigurationElements();
+			if (elements.length > 0) {
+				// this is called a lot, so don't create vector unless really
+				// needed
+				// TODO: could eventually cache in a hashtable, or something,
+				// to avoid repeat processing
+				factoryList = new Vector();
+				for (int i = 0; i < elements.length; i++) {
+					INodeAdapterFactory factory = loadFactoryFromConfigurationElement(elements[i], contentType);
+					if (factory != null)
+						factoryList.add(factory);
+				}
+			}
+		}
+		return factoryList;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/parser/ContextRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/parser/ContextRegion.java
new file mode 100644
index 0000000..caaafd5
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/parser/ContextRegion.java
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.parser;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+
+
+/**
+ * Regions of this class are intended specifically for XML/HTML/JSPs. Other
+ * languages may need their own subclasses. (See the updateModel method).
+ */
+public class ContextRegion implements ITextRegion {
+	protected int fLength;
+
+	protected int fStart;
+	protected int fTextLength;
+	protected String fType;
+
+	protected ContextRegion() {
+		super();
+	}
+
+	public ContextRegion(String newContext, int newStart, int newTextLength, int newLength) {
+		fType = newContext;
+		fStart = newStart;
+		fTextLength = newTextLength;
+		fLength = newLength;
+	}
+
+
+	public void adjust(int i) {
+		fStart += i;
+
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+	}
+
+	public void adjustStart(int i) {
+		fStart += i;
+	}
+
+	public void adjustTextLength(int i) {
+		fTextLength += i;
+
+	}
+
+	boolean allLetterOrDigit(String changes) {
+		boolean result = true;
+		for (int i = 0; i < changes.length(); i++) {
+			// TO_DO_FUTURE: check that a Java Letter or Digit is
+			// the same thing as an XML letter or digit
+			if (!(Character.isLetterOrDigit(changes.charAt(i)))) {
+				result = false;
+				break;
+			}
+		}
+		return result;
+	}
+
+	boolean allWhiteSpace(String changes) {
+		boolean result = true;
+		for (int i = 0; i < changes.length(); i++) {
+			if (!Character.isWhitespace(changes.charAt(i))) {
+				result = false;
+				break;
+			}
+		}
+
+		return result;
+	}
+
+	boolean canHandleAsLetterOrDigit(String changes, int requestStart, int lengthToReplace) {
+		boolean result = false;
+		// Make sure we are in a non-white space area
+		if ((requestStart <= (getTextEnd())) && (allLetterOrDigit(changes))) {
+			result = true;
+		}
+		return result;
+	}
+
+	boolean canHandleAsWhiteSpace(String changes, int requestStart, int lengthToReplace) {
+		boolean result = false;
+		// if we are in the "white space" area of a region, then
+		// we don't want to handle, a reparse is needed.
+		// the white space region is consider anywhere that would
+		// leave whitespace between this character and the text part.
+		// and of course, we can insert whitespace in whitespace region
+		//
+		// if there is no whitespace in this region, no need to look further
+		if (getEnd() > getTextEnd()) {
+			// no need to add one to end of text, as we used to, since we
+			// change definition of length to equate to offset plus one.
+			if (requestStart > getTextEnd()) {
+				// ok, we are in the whitespace region, so we can't handle,
+				// unless
+				// we are just inserting whitespace.
+				if (allWhiteSpace(changes)) {
+					result = true;
+				}
+				else {
+					result = false;
+				}
+
+			}
+		}
+
+		return result;
+	}
+
+	public boolean contains(int position) {
+
+		return fStart <= position && position < fStart + fLength;
+	}
+
+	public void equatePositions(ITextRegion region) {
+		fStart = region.getStart();
+		fLength = region.getLength();
+		fTextLength = region.getTextLength();
+	}
+
+	public int getEnd() {
+		return fStart + fLength;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getStart() {
+		return fStart;
+	}
+
+	public int getTextEnd() {
+		return fStart + fTextLength;
+	}
+
+	public int getTextLength() {
+		return fTextLength;
+	}
+
+	public String getType() {
+		return fType;
+	}
+
+	public void setLength(int i) {
+		fLength = i;
+	}
+
+	public void setStart(int i) {
+		fStart = i;
+	}
+
+	public void setTextLength(int i) {
+		fTextLength = i;
+	}
+
+	public void setType(String string) {
+		fType = string;
+	}
+
+	public String toString() {
+		String className = getClass().getName();
+		String shortClassName = className.substring(className.lastIndexOf(".") + 1); //$NON-NLS-1$
+		String result = shortClassName + "--> " + getType() + ": " + getStart() + "-" + getTextEnd() + (getTextEnd() != getEnd() ? ("/" + getEnd()) : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+		// NOTE: if the document held by any region has been updated and the
+		// region offsets have not
+		// yet been updated, the output from this method invalid.
+		return result;
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace) {
+		// the four types we used to handle here, have all been moved to
+		// specific region classes.
+		// XML_TAG_ATTRIBUTE_VALUE
+		// XML_TAG_ATTRIBUTE_NAME
+		// XML_CONTENT
+		// XML_CDATA_TEXT
+		return null;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/parser/ForeignRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/parser/ForeignRegion.java
new file mode 100644
index 0000000..9bb5a36
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/parser/ForeignRegion.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.parser;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+
+
+public class ForeignRegion extends ContextRegion {
+
+	private String language = null;
+	private String surroundingTag = null;
+
+	public ForeignRegion(String newContext, int newStart, int newTextLength, int newLength) {
+		super(newContext, newStart, newTextLength, newLength);
+	}
+
+	public ForeignRegion(String newContext, int newStart, int newTextLength, int newLength, String newLanguage) {
+		super(newContext, newStart, newTextLength, newLength);
+		setLanguage(newLanguage);
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String
+	 */
+	public java.lang.String getLanguage() {
+		return language;
+	}
+
+	/**
+	 * @return java.lang.String
+	 */
+	public java.lang.String getSurroundingTag() {
+		return surroundingTag;
+	}
+
+	/**
+	 * 
+	 * @param newLanguage
+	 *            java.lang.String
+	 */
+	public void setLanguage(java.lang.String newLanguage) {
+		language = newLanguage;
+	}
+
+	/**
+	 * @param newSurroundingTag
+	 *            java.lang.String
+	 */
+	public void setSurroundingTag(java.lang.String newSurroundingTag) {
+		surroundingTag = newSurroundingTag;
+	}
+
+	public String toString() {
+		return "FOREIGN: " + super.toString();//$NON-NLS-1$
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion flatnode, String changes, int requestStart, int lengthToReplace) {
+		org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent result = null;
+		int lengthDifference = org.eclipse.wst.sse.core.internal.util.Utilities.calculateLengthDifference(changes, lengthToReplace);
+		fLength += lengthDifference;
+		fTextLength += lengthDifference;
+		result = new RegionChangedEvent(flatnode.getParentDocument(), requester, flatnode, this, changes, requestStart, lengthToReplace);
+
+		return result;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/preferences/CommonModelPreferenceNames.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/preferences/CommonModelPreferenceNames.java
new file mode 100644
index 0000000..a7ef278
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/preferences/CommonModelPreferenceNames.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.preferences;
+
+/**
+ * @deprecated CommonModelPreferenceNames are now managed by each individual
+ *             content type. (XXCorePreferenceNames)
+ * 
+ */
+public interface CommonModelPreferenceNames {
+	String TAB_WIDTH = "tabWidth";//$NON-NLS-1$
+	String LINE_WIDTH = "lineWidth";//$NON-NLS-1$
+	String SPLIT_MULTI_ATTRS = "splitMultiAttrs";//$NON-NLS-1$
+	String INDENT_USING_TABS = "indentUsingTabs";//$NON-NLS-1$
+	String CLEAR_ALL_BLANK_LINES = "clearAllBlankLines";//$NON-NLS-1$
+
+	String TAG_NAME_CASE = "tagNameCase";//$NON-NLS-1$
+	String ATTR_NAME_CASE = "attrNameCase";//$NON-NLS-1$
+
+	String FORMATTING_SUPPORTED = "formattingSupported";//$NON-NLS-1$
+
+	String PREFERRED_MARKUP_CASE_SUPPORTED = "preferredMarkupCaseSupported";//$NON-NLS-1$
+
+	String TASK_TAG_TAGS = "task-tag-tags"; //$NON-NLS-1$
+	String TASK_TAG_PRIORITIES = "task-tag-priorities"; //$NON-NLS-1$
+	String TASK_TAG_ENABLE = "task-tags"; //$NON-NLS-1$
+	String TASK_TAG_PROJECTS_IGNORED = "task-tag-projects-toIgnore"; //$NON-NLS-1$
+
+
+	/**
+	 * these are preferences that should be inherited from the "embedded
+	 * preference store" for example: if you ask for th OVERVIEW_RULER
+	 * preference for JSP, you will automatically get the preference from the
+	 * HTML preference store.
+	 */
+	String EMBEDDED_CONTENT_TYPE_PREFERENCES[] = {TAB_WIDTH, LINE_WIDTH, SPLIT_MULTI_ATTRS, INDENT_USING_TABS, CLEAR_ALL_BLANK_LINES, TAG_NAME_CASE, ATTR_NAME_CASE,};
+
+	String FORMATTING_PREFERENCES[] = {TAB_WIDTH, LINE_WIDTH, SPLIT_MULTI_ATTRS, INDENT_USING_TABS, CLEAR_ALL_BLANK_LINES,};
+
+	String AUTO = "Auto";//$NON-NLS-1$
+	String UTF_8 = "UTF-8";//$NON-NLS-1$
+	String ISO_8859_1 = "ISO-8859-1";//$NON-NLS-1$
+
+	int ASIS = 0;
+	int LOWER = 1;
+	int UPPER = 2;
+
+	// cleanup preference names
+	String CLEANUP_TAG_NAME_CASE = "cleanupTagNameCase";//$NON-NLS-1$
+	String CLEANUP_ATTR_NAME_CASE = "cleanupAttrNameCase";//$NON-NLS-1$
+	String COMPRESS_EMPTY_ELEMENT_TAGS = "compressEmptyElementTags";//$NON-NLS-1$
+	String INSERT_REQUIRED_ATTRS = "insertRequiredAttrs";//$NON-NLS-1$
+	String INSERT_MISSING_TAGS = "insertMissingTags";//$NON-NLS-1$
+	String QUOTE_ATTR_VALUES = "quoteAttrValues";//$NON-NLS-1$
+	String FORMAT_SOURCE = "formatSource";//$NON-NLS-1$
+	String CONVERT_EOL_CODES = "convertEOLCodes";//$NON-NLS-1$
+	String CLEANUP_EOL_CODE = "cleanupEOLCode";//$NON-NLS-1$
+
+	String LAST_ACTIVE_PAGE = "lastActivePage";//$NON-NLS-1$	
+
+	// need to put default tab width preference here so it is accessible by
+	// both model and editor
+	// this way, editor does not need to query model's default tab width
+	// preference
+	int DEFAULT_TAB_WIDTH = 4;
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/preferences/PreferenceInitializer.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/preferences/PreferenceInitializer.java
new file mode 100644
index 0000000..7505633
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/preferences/PreferenceInitializer.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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.wst.sse.core.internal.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.wst.sse.core.internal.tasks.TaskTagPreferenceKeys;
+
+public class PreferenceInitializer extends AbstractPreferenceInitializer {
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+	 */
+	public void initializeDefaultPreferences() {
+		IEclipsePreferences taskTagDefaults = new DefaultScope().getNode(TaskTagPreferenceKeys.TASK_TAG_NODE);
+		taskTagDefaults.putBoolean(TaskTagPreferenceKeys.TASK_TAG_ENABLE, false);
+		taskTagDefaults.put(TaskTagPreferenceKeys.TASK_TAG_TAGS, "TODO,FIXME,XXX"); //$NON-NLS-1$
+		taskTagDefaults.put(TaskTagPreferenceKeys.TASK_TAG_PRIORITIES, "1,2,1"); //$NON-NLS-1$
+		taskTagDefaults.put(TaskTagPreferenceKeys.TASK_TAG_CONTENTTYPES_IGNORED, ""); //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/propertytester/StructuredFilePropertyTester.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/propertytester/StructuredFilePropertyTester.java
new file mode 100644
index 0000000..184bc03
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/propertytester/StructuredFilePropertyTester.java
@@ -0,0 +1,85 @@
+/******************************************************************************
+ * Copyright (c) 2008 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.wst.sse.core.internal.propertytester;
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.wst.sse.core.internal.Logger;
+
+/**
+ * A Property Tester that operates on IFiles and validates
+ * that the expected content type id matches that of the content
+ * type of the file, or any of the base content types.
+ * 
+ * Based on org.eclipse.core.internal.propertytester.FilePropertyTester
+ * 
+ * @deprecated use org.eclipse.core.resources.contentTypeId instead
+ * 
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=288216 
+ */
+public class StructuredFilePropertyTester extends PropertyTester {
+
+	/**
+	 * A property indicating that we are looking to verify that the file matches
+	 * the content type matching the given identifier. The identifier is
+	 * provided as the expected value.
+	 */
+	private static final String PROPERTY_CONTENT_TYPE_ID = "contentTypeId"; //$NON-NLS-1$
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.core.expressions.IPropertyTester#test(java.lang.Object, java.lang.String, java.lang.Object[], java.lang.Object)
+	 */
+	public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
+		if(PROPERTY_CONTENT_TYPE_ID.equals(property) && (expectedValue != null) && (receiver instanceof IFile) && ((IFile) receiver).exists())
+			return testContentType((IFile) receiver, expectedValue.toString());
+		return false;
+	}
+	
+	/**
+	 * Tests whether the content type for <code>file</code> (or any base content types) 
+	 * matches the <code>contentTypeId</code>. It is possible that this method call could
+	 * cause the file to be read. It is also possible (through poor plug-in
+	 * design) for this method to load plug-ins.
+	 * 
+	 * @param file
+	 *            The file for which the content type should be determined; must
+	 *            not be <code>null</code>.
+	 * @param contentTypeId
+	 *            The expected content type; must not be <code>null</code>.
+	 * @return <code>true</code> if the file's content type (or base content types) 
+	 *         has an identifier that matches <code>contentTypeId</code>;
+	 *         <code>false</code> otherwise.
+	 */
+	private boolean testContentType(final IFile file, String contentTypeId) {
+		final String expectedValue = contentTypeId.trim();
+
+		try {
+			IContentDescription contentDescription = file.getContentDescription();
+			if (contentDescription != null) {
+				IContentType contentType = contentDescription.getContentType();
+				while (contentType != null) {
+					if (expectedValue.equals(contentType.getId()))
+						return true;
+					contentType = contentType.getBaseType();
+				}
+			}
+		}
+		catch (Exception e) {
+			// [232831] - Log messages only when debugging
+			if(Logger.DEBUG)
+				Logger.logException(e);
+		}
+		return false;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/AbstractAdapterFactory.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/AbstractAdapterFactory.java
new file mode 100644
index 0000000..4aa9c80
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/AbstractAdapterFactory.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional;
+
+/**
+ * An abstract implementation of IAdapterFactory. All implementers of
+ * IAdapterFactory should subclass this class. The default constructor uses
+ * itself (this) as the key. Subclasses need to provide a way to create the
+ * adapter, and can override or call other methods.
+ */
+abstract public class AbstractAdapterFactory implements INodeAdapterFactory {
+
+
+
+	private Object fAdapterKey;
+
+	private boolean fShouldRegisterAdapter;
+
+	/**
+	 * If this default constructor used, setAdapterKey and setShouldRegister
+	 * should be used to properly initialize.
+	 */
+	protected AbstractAdapterFactory() {
+		super();
+
+	}
+
+
+	public AbstractAdapterFactory(Object adapterKey) {
+		this(adapterKey, true);
+	}
+
+	/**
+	 * Suclasses may extended this constructor, if needed.
+	 */
+
+	public AbstractAdapterFactory(Object adapterKey, boolean registerAdapters) {
+
+		super();
+		fAdapterKey = adapterKey;
+		fShouldRegisterAdapter = registerAdapters;
+
+	}
+
+	/**
+	 * ISSUE: should be final. See those that implement it 
+	 * for complicating details and "unknowns". 
+	 */
+	public INodeAdapter adapt(INodeNotifier target) {
+		INodeAdapter adapter = null;
+		if (target != null) {
+			adapter = target.getExistingAdapter(fAdapterKey);
+			if (adapter == null) {
+				adapter = adaptNew(target);
+			}
+		}
+		return adapter;
+	}
+
+	/**
+	 * Subclasses should normally implement their own 'copy' method. By
+	 * default, we'll return the same instance, for convenience of those using
+	 * singleton factories (which have no state, and so need to do anything on
+	 * 'release').
+	 * 
+	 */
+	public INodeAdapterFactory copy() {
+		return this;
+	}
+
+	/**
+	 * This method needs to return true of this factory is for adapters of
+	 * type 'type'. It is required that it return true if 'equals' and this
+	 * default behavior is provided by this super class. Clients may extend
+	 * this behavior if more complex logic is required.
+	 */
+	public boolean isFactoryForType(Object type) {
+		return type.equals(fAdapterKey);
+	}
+
+	/**
+	 * Subclasses may need to "cleanup" their adapter factory, release
+	 * adapters, resources, etc. Subclasses may extend this method if such
+	 * clean up is required. Note: while current behavior is to do nothing,
+	 * subclasses should not assume this would always be true, so should
+	 * always call super.release at the end of their method.
+	 */
+	public void release() {
+		// default for superclass is to do nothing
+	}
+
+	/**
+	 * Only for special cases there the adapter key can be set in the
+	 * constructor. It can be set here. If it is set more than, and
+	 */
+	final protected void setAdapterKey(Object key) {
+		if (fAdapterKey != null && !(fAdapterKey.equals(key)))
+			throw new IllegalStateException("INodeAdapter Key cannot be changed."); //$NON-NLS-1$
+		fAdapterKey = key;
+	}
+
+	/**
+	 * Can be called by subclasses during 'adapt' process, but must not be
+	 * overridden or reimplemented by subclasses.
+	 * 
+	 * @param target
+	 * @return
+	 */
+	protected final INodeAdapter adaptNew(INodeNotifier target) {
+		INodeAdapter adapter = createAdapter(target);
+		if (adapter != null) {
+			if (fShouldRegisterAdapter) {
+				target.addAdapter(adapter);
+			}
+		}
+		return adapter;
+	}
+
+	/**
+	 * Subclasses must implement this method. It is called by infrastructure
+	 * when an instance is needed. It is provided the node notifier, which may
+	 * or may not be relevent when creating the adapter. Note: the adapter
+	 * does not have to literally be a new intance and is actually recommended
+	 * to typically be a singleton for performance reasons.
+	 * 
+	 * @param target
+	 * @return
+	 */
+	abstract protected INodeAdapter createAdapter(INodeNotifier target);
+
+
+	protected final boolean isShouldRegisterAdapter() {
+		return fShouldRegisterAdapter;
+	}
+
+
+	protected final void setShouldRegisterAdapter(boolean shouldRegisterAdapter) {
+		// ISSUE: technically we probably should not allow this value to
+		// change, after initialization, but is not so easy to do,
+		// and I'm not sure its "worth" the protection.
+		fShouldRegisterAdapter = shouldRegisterAdapter;
+	}
+
+
+	protected final Object getAdapterKey() {
+		return fAdapterKey;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/AbstractNotifier.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/AbstractNotifier.java
new file mode 100644
index 0000000..6f18471
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/AbstractNotifier.java
@@ -0,0 +1,240 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.model.FactoryRegistry;
+
+
+
+/**
+ * AbstractNotifier is similar to (and based on) the EMF NotifierImpl class,
+ * but is not related to EMF per se. This class is simpler (that is, not as
+ * many functions).
+ * 
+ * Implementers of this INodeNotifier must subclass this class.
+ */
+public abstract class AbstractNotifier implements INodeNotifier {
+	private final static int growthConstant = 3;
+	private int adapterCount = 0;
+
+	private INodeAdapter[] fAdapters;
+
+	/**
+	 * AbstractNotifier constructor comment.
+	 */
+	public AbstractNotifier() {
+		super();
+	}
+
+	/**
+	 * addAdapter method comment.
+	 */
+	public synchronized void addAdapter(INodeAdapter adapter) {
+
+		if (adapter == null)
+			return;
+		ensureCapacity(adapterCount + 1);
+		fAdapters[adapterCount++] = adapter;
+	}
+
+	private synchronized void ensureCapacity(int needed) {
+		if (fAdapters == null) {
+			// first time
+			fAdapters = new INodeAdapter[needed + growthConstant];
+			return;
+		}
+		int oldLength = fAdapters.length;
+		if (oldLength < needed) {
+			INodeAdapter[] oldAdapters = fAdapters;
+			INodeAdapter[] newAdapters = new INodeAdapter[needed + growthConstant];
+			System.arraycopy(oldAdapters, 0, newAdapters, 0, adapterCount);
+			fAdapters = newAdapters;
+		}
+	}
+
+	/**
+	 * NOT API: used only for testing.
+	 * 
+	 * @return int
+	 */
+	public int getAdapterCount() {
+		return adapterCount;
+	}
+
+	/**
+	 * Default behavior for getting an adapter.
+	 */
+	public synchronized INodeAdapter getAdapterFor(Object type) {
+		// first, we'll see if we already have one
+		INodeAdapter result = getExistingAdapter(type);
+		// if we didn't find one in our list already,
+		// let's create it
+		if (result == null) {
+			FactoryRegistry reg = getFactoryRegistry();
+			if (reg != null) {
+				INodeAdapterFactory factory = reg.getFactoryFor(type);
+				if (factory != null) {
+					result = factory.adapt(this);
+				}
+			}
+			// We won't prevent null from being returned, but it would be
+			// unusual.
+			// It might be because Factory is not working correctly, or
+			// not installed, so we'll allow warning message.
+			if ((result == null) && (org.eclipse.wst.sse.core.internal.util.Debug.displayWarnings)) {
+				System.out.println("Warning: no adapter was found or created for " + type); //$NON-NLS-1$
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Returns a shallow clone of list, since clients should not manipulate
+	 * our list directly. Instead, they should use add/removeAdapter.
+	 */
+	public synchronized Collection getAdapters() {
+		if (fAdapters != null) {
+			if (adapterCount == 0) {
+				fAdapters = null;
+				return Collections.EMPTY_LIST;
+			}
+			else {
+				// we need to make a new array, to be sure
+				// it doesn't contain nulls at end, which may be
+				// present there for "growth".
+				INodeAdapter[] tempAdapters = new INodeAdapter[adapterCount];
+				System.arraycopy(fAdapters, 0, tempAdapters, 0, adapterCount);
+				// EMF uses the unmodifiableCollection. Its a bit of a
+				// performance
+				// drain, but may want to leave in since
+				// it would "fail fast" if someone was trying to modify the
+				// list.
+				return Collections.unmodifiableCollection(Arrays.asList(tempAdapters));
+				// return Arrays.asList(newAdapters);
+			}
+		}
+		else
+			return Collections.EMPTY_LIST;
+	}
+
+	private long getAdapterTimeCriteria() {
+		// to "re-get" the property each time is a little awkward, but we
+		// do it that way to avoid adding instance variable just for
+		// debugging.
+		// This method should only be called if debugAdapterNotifcationTime
+		// is true.
+		final String criteriaStr = Platform.getDebugOption("org.eclipse.wst.sse.core/dom/adapter/notification/time/criteria"); //$NON-NLS-1$
+		long criteria = -1;
+		if (criteriaStr != null) {
+			try {
+				criteria = Long.parseLong(criteriaStr);
+			}
+			catch (NumberFormatException e) {
+				// catch to be sure we don't burb in notification loop,
+				// but ignore, since just a debug aid
+			}
+		}
+		return criteria;
+	}
+
+	public synchronized INodeAdapter getExistingAdapter(Object type) {
+		INodeAdapter result = null;
+		for (int i = 0; i < adapterCount; i++) {
+			INodeAdapter a = fAdapters[i];
+			if (a != null && a.isAdapterForType(type)) {
+				result = a;
+				break;
+			}
+		}
+		// if we didn't find one in our list,
+		// return the null result
+		return result;
+	}
+
+	abstract public FactoryRegistry getFactoryRegistry();
+
+	public void notify(int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
+
+		int localAdapterCount = 0;
+		INodeAdapter[] localAdapters = null;
+
+		// lock object while making local assignments
+		synchronized (this) {
+			if (fAdapters != null) {
+				localAdapterCount = adapterCount;
+				localAdapters = new INodeAdapter[localAdapterCount];
+				System.arraycopy(fAdapters, 0, localAdapters, 0, localAdapterCount);
+			}
+		}
+
+		for (int i = 0; i < localAdapterCount; i++) {
+			INodeAdapter a = localAdapters[i];
+
+			if (Logger.DEBUG_ADAPTERNOTIFICATIONTIME) {
+				long getAdapterTimeCriteria = getAdapterTimeCriteria();
+				long startTime = System.currentTimeMillis();
+				// ** keep this line identical with non-debug version!!
+				a.notifyChanged(this, eventType, changedFeature, oldValue, newValue, pos);
+				long notifyDuration = System.currentTimeMillis() - startTime;
+				if (getAdapterTimeCriteria >= 0 && notifyDuration > getAdapterTimeCriteria) {
+					System.out.println("adapter notifyDuration: " + notifyDuration + "  class: " + a.getClass()); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+			else {
+				try {
+					// ** keep this line identical with debug version!!
+					a.notifyChanged(this, eventType, changedFeature, oldValue, newValue, pos);
+				}
+				catch (Exception e) {
+					// Its important to "keep going", since notifications
+					// occur between an
+					// aboutToChange event and a changed event -- the
+					// changed event typically being require
+					// to restore state, etc. So, we just log message, do
+					// not re-throw it, but
+					// typically the exception does indicate a serious
+					// program error.
+					Logger.logException("A structured model client, " + a + " threw following exception during adapter notification (" + INodeNotifier.EVENT_TYPE_STRINGS[eventType] + " )", e); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+				}
+			}
+
+		}
+	}
+
+	public synchronized void removeAdapter(INodeAdapter a) {
+		if (fAdapters == null || a == null)
+			return;
+		int newIndex = 0;
+		INodeAdapter[] newAdapters = new INodeAdapter[fAdapters.length];
+		int oldAdapterCount = adapterCount;
+		boolean found = false;
+		for (int oldIndex = 0; oldIndex < oldAdapterCount; oldIndex++) {
+			INodeAdapter candidate = fAdapters[oldIndex];
+			if (a == candidate) {
+				adapterCount--;
+				found = true;
+			}
+			else
+				newAdapters[newIndex++] = fAdapters[oldIndex];
+		}
+		if (found)
+			fAdapters = newAdapters;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/DocumentChanged.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/DocumentChanged.java
new file mode 100644
index 0000000..6d7a4ec
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/DocumentChanged.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional;
+
+import org.eclipse.wst.sse.core.internal.model.ModelLifecycleEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+public class DocumentChanged extends ModelLifecycleEvent {
+	private IStructuredDocument fNewDocument;
+
+	private IStructuredDocument fOldDocument;
+
+	protected DocumentChanged() {
+
+		super(ModelLifecycleEvent.MODEL_DOCUMENT_CHANGED);
+
+	}
+
+	protected DocumentChanged(int additionalType, IStructuredModel model) {
+
+		super(model, ModelLifecycleEvent.MODEL_DOCUMENT_CHANGED | additionalType);
+
+	}
+
+	public DocumentChanged(int additionalType, IStructuredModel model, IStructuredDocument oldDocument, IStructuredDocument newDocument) {
+
+		this(additionalType, model);
+		fOldDocument = oldDocument;
+		fNewDocument = newDocument;
+	}
+
+	public IStructuredDocument getNewDocument() {
+
+		return fNewDocument;
+	}
+
+	public IStructuredDocument getOldDocument() {
+
+		return fOldDocument;
+	}
+
+	void setNewDocument(IStructuredDocument newDocument) {
+
+		fNewDocument = newDocument;
+	}
+
+	void setOldDocument(IStructuredDocument oldDocument) {
+
+		fOldDocument = oldDocument;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IModelLifecycleListener.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IModelLifecycleListener.java
new file mode 100644
index 0000000..87f8353
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IModelLifecycleListener.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional;
+
+import org.eclipse.wst.sse.core.internal.model.ModelLifecycleEvent;
+
+/**
+ * This is an early version of a class that may change over the next few
+ * milestones.
+ */
+
+public interface IModelLifecycleListener {
+
+	void processPostModelEvent(ModelLifecycleEvent event);
+
+	void processPreModelEvent(ModelLifecycleEvent event);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IModelLoader.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IModelLoader.java
new file mode 100644
index 0000000..53308f0
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IModelLoader.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingRule;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+
+/**
+ * Responsible for creating a new Model from a resource, or as a new, empty
+ * instance.
+ * 
+ */
+public interface IModelLoader {
+	/**
+	 * This method should perform all the model initialization required before
+	 * it contains content, namely, it should call newModel, the
+	 * createNewStructuredDocument(), then setAdapterFactories. (this is
+	 * tentative)
+	 */
+	IStructuredModel createModel();
+
+	/**
+	 * Method createModel. Creates a new model based on old one.
+	 * 
+	 * @param oldModel
+	 * @return IStructuredModel
+	 */
+	IStructuredModel createModel(IStructuredModel oldModel);
+
+	/**
+	 * This method must return those factories which must be attached to the
+	 * structuredModel before content is applied.
+	 */
+	List getAdapterFactories();
+
+	void load(IFile file, IStructuredModel model) throws IOException, CoreException;
+
+	void load(InputStream inputStream, IStructuredModel model, EncodingRule encodingRule) throws IOException;
+
+	void load(String filename, InputStream inputStream, IStructuredModel model, String encodingName, String lineDelimiter) throws IOException;
+
+	IModelLoader newInstance();
+
+	/**
+	 * This method should always return an new, empty Structured Model
+	 * appropriate for itself.
+	 */
+	IStructuredModel newModel();
+
+	IStructuredModel reinitialize(IStructuredModel model);
+
+	/**
+	 * This method should get a fresh copy of the data, and repopulate the
+	 * models ... normally by a call to setText on the structuredDocument, for
+	 * StructuredModels. This method is needed in some cases where clients are
+	 * sharing a model and then changes canceled. Say for example, one editor
+	 * and several "displays" are sharing a model, if the editor is closed
+	 * without saving changes, then the displays still need a model, but they
+	 * should revert to the original unsaved version.
+	 */
+	void reload(InputStream inputStream, IStructuredModel model);
+
+	/**
+	 * Create a Structured Model with the given StructuredDocument instance as
+	 * its document (instead of a new document instance as well)
+	 */
+	IStructuredModel createModel(IStructuredDocument document, String baseLocation, IModelHandler handler);
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IModelManager.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IModelManager.java
new file mode 100644
index 0000000..b23d0fa
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IModelManager.java
@@ -0,0 +1,554 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Enumeration;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingRule;
+import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceAlreadyExists;
+import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceInUse;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.util.URIResolver;
+
+/**
+ * <p>
+ * Provides APIs for managing (get, release, save, and save as) SSE Structured
+ * Models.
+ * </p>
+ * <p>
+ * Structured Models created from an implementor of this interface can be
+ * either managed or unmanaged. Managed models are shared using reference
+ * counts, so until that count has been decremented to zero, the model will
+ * continue to exist in memory. When managed, models can be looked up using
+ * their IDs or their IStructuredDocuments, which can be advantageous when
+ * building on APIs that aren't specifically designed for SSE (such as those
+ * revolving around IDocuments). Unmanaged models offer no such features, and
+ * are largely used for tasks where their contents are ephemeral, such as for
+ * populating a source viewer with syntax-colored content.
+ * </p>
+ * <p>
+ * There are two types of access used when retrieving a model from the model
+ * manager: READ and EDIT. The contents of a model can be modified regardless
+ * of which access type is used, but any client who gets a model for EDIT is
+ * explicitly declaring that they are interested in saving those changed
+ * contents. The EDIT and READ reference counts are visible to everyone, as
+ * are convenience methods for determining whether a managed model is shared
+ * among multiple clients accessing it for READ or EDIT.
+ * </p>
+ * <p>
+ * Managed models whose contents are "dirty" with READ and EDIT counts above
+ * zero will be reverted to the on-disk content if the EDIT count drops to
+ * zero while the READ count remains above zero.
+ * </p>
+ * <p>
+ * Shared models for which the read and edit counts have both dropped to zero
+ * are no longer valid for use, regardless of whether they have been garbage
+ * collected or not. It is possible, but not guaranteed, that the underlying
+ * structured document is still valid and may even be used in constructing a
+ * new shared model.
+ * </p>
+ * <p>
+ * 
+ * @noimplement This interface is not intended to be implemented by clients.
+ * Clients should obtain an instance of the IModelManager interface through
+ * {@link StructuredModelManager#getModelManager()}.</p>
+ *              </p>
+ *              <p>
+ * @see {@link StructuredModelManager}</p>
+ */
+public interface IModelManager {
+
+	/**
+	 * A fixed ID used for models which were created as duplicates of existing
+	 * models
+	 */
+	public final static String DUPLICATED_MODEL = "org.eclipse.wst.sse.core.IModelManager.DUPLICATED_MODEL"; //$NON-NLS-1$
+
+	/**
+	 * A fixed ID used for unmanaged models
+	 */
+	public final static String UNMANAGED_MODEL = "org.eclipse.wst.sse.core.IModelManager.UNMANAGED_MODEL"; //$NON-NLS-1$
+
+	/**
+	 * Calculate id provides a common way to determine the id from the input
+	 * ... needed to get and save the model. It is a simple class utility, but
+	 * is an instance method so can be accessed via interface.
+	 */
+	public String calculateId(IFile file);
+
+	/**
+	 * Copies a model with the old id 
+	 * @param oldId - the old model's ID
+	 * @param newId - the new model's ID
+	 * @return the new model
+	 * @throws ResourceInUse if the given new ID is already in use by a managed model
+	 */
+	IStructuredModel copyModelForEdit(String oldId, String newId) throws ResourceInUse;
+
+	/**
+	 * Creates a new, but empty, unmanaged model of the same kind as the one
+	 * given. For a managed model with the same contents, use "copy".
+	 * 
+	 * @param model
+	 * @return the model, or null of one could not be created
+	 * @throws IOException if the file's contents can not be read or its detected encoding does not support its contents
+	 */
+	public IStructuredModel createNewInstance(IStructuredModel model) throws IOException;
+
+	/**
+	 * Factory method, since a proper IStructuredDocument must have a proper
+	 * parser assigned. If the resource does already exist, then
+	 * createStructuredDocumentFor is the right API to use.
+	 * 
+	 * @param iFile
+	 * @return the document, or null if one could not be created
+	 * @throws ResourceAlreadyExists
+	 *             if the IFile already exists
+	 * @throws CoreException if the file's contents or description can not be read
+	 * @throws IOException if the file's contents can not be read or its detected encoding does not support its contents
+	 * @throws ResourceAlreadyExists if the give file already exists
+	 */
+	IStructuredDocument createNewStructuredDocumentFor(IFile iFile) throws ResourceAlreadyExists, IOException, CoreException;
+
+	/**
+	 * Factory method, since a proper IStructuredDocument must have a proper
+	 * parser assigned. Note: clients should verify IFile exists before using
+	 * this method. If this IFile does not exist, then
+	 * {@link #createNewStructuredDocumentFor(IFile)} is the correct API to use.
+	 * 
+	 * @param iFile - the file
+	 * @return the document, or null if one could not be created
+	 * 
+	 * @throws CoreException if the file's contents or description can not be read
+	 * @throws IOException if the file's contents can not be read or its detected encoding does not support its contents
+	 */
+	IStructuredDocument createStructuredDocumentFor(IFile iFile) throws IOException, CoreException;
+
+	/**
+	 * Convenience method, since a proper IStructuredDocument must have a
+	 * proper parser assigned. It should only be used when an empty
+	 * structuredDocument is needed. Otherwise, use IFile form.
+	 * 
+	 * @param contentTypeId
+	 * @return a structured document with the correct parsing setup for the
+	 *         given content type ID, or null if one could not be created or
+	 *         the given content type ID is unknown or unsupported
+	 */
+	IStructuredDocument createStructuredDocumentFor(String contentTypeId);
+
+	/**
+	 * @deprecated - use IFile form instead as the correct encoding and content rules may not be applied otherwise
+	 * 
+	 * Creates and returns a properly configured structured document for the given contents with the given name
+	 * 
+	 * @param filename - the filename, which may be used to guess the content type
+	 * @param contents - the contents to load
+	 * @param resolver - the URIResolver to use for locating any needed resources
+	 * @return the IStructuredDocument or null of one could not be created
+	 * @throws IOException if the file's contents can not be read or its content type can not be determined
+	 */ 
+	IStructuredDocument createStructuredDocumentFor(String filename, InputStream contents, URIResolver resolver) throws IOException;
+
+	/**
+	 * Creates and returns a properly configured structured document for the given contents with the given name
+	 * 
+	 * @param filename - the filename, which may be used to guess the content type
+	 * @param inputStream - the contents to load
+	 * @param resolver - the URIResolver to use for locating any needed resources
+	 * @param ianaEncodingName - the IANA specified encoding to use when reading the contents
+	 * @return the IStructuredDocument or null if one could not be created
+	 * @throws IOException if the file's contents can not be read or its content type can not be determined
+	 * @deprecated - clients should convert the InputStream into text themselves
+	 *             and then use the version of this method taking a String for its
+	 *             content
+	 */
+	IStructuredDocument createStructuredDocumentFor(String filename, InputStream inputStream, URIResolver resolver, String ianaEncodingName) throws IOException;
+
+	/**
+	 * Creates and returns a properly configured structured document for the given contents with the given name
+	 * 
+	 * @param filename - the filename, which may be used to guess the content type
+	 * @param content - the contents to load
+	 * @param resolver - the URIResolver to use for locating any referenced resources
+	 * @return a structured document with the correct parsing setup for the
+	 *         given filename, or null if one could not be created
+	 * @throws IOException if the file's contents can not be read or its detected encoding does not support its contents
+	 */
+	IStructuredDocument createStructuredDocumentFor(String filename, String content, URIResolver resolver) throws IOException;
+
+	/**
+	 * Creates and returns an unmanaged model populated with the given IFile's
+	 * contents
+	 * 
+	 * @param iFile
+	 * @return a structured model, or null if one could not be created
+	 * @throws CoreException if the file's contents or description can not be read
+	 * @throws IOException if the file's contents can not be read or its detected encoding does not support its contents
+	 */
+	IStructuredModel createUnManagedStructuredModelFor(IFile iFile) throws IOException, CoreException;
+
+	/**
+	 * Convenience method. It depends on the loader's newModel method to return
+	 * an appropriate StrucuturedModel appropriately initialized.
+	 * 
+	 * @param contentTypeId
+	 * @return a structured model for the given content type, or null if one could not be created or the content type is unsupported
+	 */
+	IStructuredModel createUnManagedStructuredModelFor(String contentTypeId);
+
+	/**
+	 * @deprecated
+	 */
+	IStructuredModel createUnManagedStructuredModelFor(String contentTypeId, URIResolver resolver);
+
+	/**
+	 * Note: callers of this method must still release the model when finished.
+	 * 
+	 * @param document
+	 * @return the structured model containing the give document, incrementing
+	 *         its edit count, or null if there is not a model corresponding
+	 *         to this document.
+	 */
+	IStructuredModel getExistingModelForEdit(IDocument document);
+
+	/**
+	 * @param file
+	 * @return the structured model for the given file, incrementing its edit
+	 *         count, or null if one does not already exist for this file.
+	 */
+	IStructuredModel getExistingModelForEdit(IFile file);
+
+	/**
+	 * @param id
+	 * @return the structured model with the given ID, incrementing its edit
+	 *         count, or null if one does not already exist for this ID
+	 */
+	public IStructuredModel getExistingModelForEdit(Object id);
+
+	/**
+	 * Note: callers of this method must still release the model when finished.
+	 * 
+	 * @param document
+	 * @return the structured model containing the give document, incrementing
+	 *         its read count, or null if there is not a model corresponding
+	 *         to this document.
+	 */
+	IStructuredModel getExistingModelForRead(IDocument document);
+
+	/**
+	 * @param file
+	 * @return the structured model for the given file, incrementing its read
+	 *         count, or null if one does not already exist for this file.
+	 */
+	public IStructuredModel getExistingModelForRead(IFile iFile);
+
+	/**
+	 * @param id
+	 * @return the structured model with the given ID, incrementing its edit
+	 *         count, or null if one does not already exist for this ID
+	 */
+	public IStructuredModel getExistingModelForRead(Object id);
+
+	/**
+	 * @deprecated - internal information
+	 */
+	public Enumeration getExistingModelIds();
+
+	/**
+	 * Returns a structured model for the given file. If one does not already
+	 * exists, one will be created with an edit count of 1. If one already
+	 * exists, its edit count will be incremented before it is returned.
+	 * 
+	 * @param iFile
+	 * @return a structured model for the given file, or null if one could not
+	 *         be found or created
+	 * @throws CoreException if the file's contents or description can not be read
+	 * @throws IOException if the file's contents can not be read or its detected encoding does not support its contents
+	 */
+	public IStructuredModel getModelForEdit(IFile iFile) throws IOException, CoreException;
+
+	/**
+	 * Returns a structured model for the given file. If one does not already
+	 * exists, one will be created with an edit count of 1. If one already
+	 * exists, its edit count will be incremented before it is returned.
+	 * 
+	 * @param iFile
+	 * @param encodingRule the rule for handling encoding
+	 * @return a structured model for the given file, or null if one could not
+	 *         be found or created
+	 * @throws CoreException if the file's contents or description can not be read
+	 * @throws IOException if the file's contents can not be read or its detected encoding does not support its contents
+	 * @deprecated - encoding is handled automatically based on the file's
+	 *             contents or user preferences
+	 */
+	public IStructuredModel getModelForEdit(IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException;
+
+	/**
+	 * @deprecated - Encoding and the line delimiter used are handled
+	 *             automatically based on the file's contents or user
+	 *             preferences.
+	 */
+	public IStructuredModel getModelForEdit(IFile iFile, String encoding, String lineDelimiter) throws UnsupportedEncodingException, IOException, CoreException;
+
+	/**
+	 * Returns a structured model for the given document. If one does not
+	 * already exists, one will be created with an edit count of 1. If one
+	 * already exists, its edit count will be incremented before it is
+	 * returned. This method is intended only to interact with documents
+	 * contained within File Buffers.
+	 * 
+	 * @param textFileBufferDocument
+	 * @return a structured model for the given document, or null if there is
+	 *         insufficient information known about the document instance to
+	 *         do so
+	 */
+	public IStructuredModel getModelForEdit(IStructuredDocument textFileBufferDocument);
+
+	/**
+	 * Returns a structured model for the given contents using the given ID.
+	 * If one does not already exist, one will be created with an edit count
+	 * of 1. If one already exists, its edit count will be incremented before
+	 * it is returned.
+	 * 
+	 * @param id
+	 *            - the id for the model
+	 * @param inStream
+	 *            - the initial contents of the model
+	 * @param resolver
+	 *            - the URIResolver to use for locating any needed resources
+	 * @return a structured model for the given content, or null if one could
+	 *         not be found or created
+	 * @throws UnsupportedEncodingException
+	 * @throws IOException
+	 *             if the contents can not be read or its detected encoding
+	 *             does not support its contents
+	 * @deprecated - a URI resolver should be automatically created when
+	 *             needed
+	 */
+	public IStructuredModel getModelForEdit(String id, InputStream inStream, URIResolver resolver) throws UnsupportedEncodingException, IOException;
+
+	/**
+	 * Returns a structured model for the given file. If one does not already
+	 * exists, one will be created with a read count of 1. If one already
+	 * exists, its read count will be incremented before it is returned.
+	 * 
+	 * @param iFile
+	 * @return a structured model for the given file, or null if one could not
+	 *         be found or created
+	 * @throws CoreException if the file's contents or description can not be read
+	 * @throws IOException if the file's contents can not be read or its detected encoding does not support its contents
+	 */
+	public IStructuredModel getModelForRead(IFile iFile) throws IOException, CoreException;
+
+	/**
+	 * @deprecated - encoding is handled automatically based on the file's
+	 *             contents or user preferences
+	 */
+	public IStructuredModel getModelForRead(IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException;
+
+	/**
+	 * @deprecated - Encoding and the line delimiter used are handled
+	 *             automatically based on the file's contents or user
+	 *             preferences.
+	 */
+	public IStructuredModel getModelForRead(IFile iFile, String encoding, String lineDelimiter) throws UnsupportedEncodingException, IOException, CoreException;
+
+	/**
+	 * Returns a structured model for the given document. If one does not
+	 * already exists, one will be created with a read count of 1. If one
+	 * already exists, its read count will be incremented before it is
+	 * returned. This method is intended only to interact with documents
+	 * contained within File Buffers.
+	 * 
+	 * @param textFileBufferDocument
+	 * @return a structured model for the given document, or null if there is
+	 *         insufficient information known about the document instance to
+	 *         do so
+	 */
+	public IStructuredModel getModelForRead(IStructuredDocument textFileBufferDocument);
+
+	/**
+	 * Returns a structured model for the given contents using the given ID.
+	 * If one does not already exist, one will be created with an read count
+	 * of 1. If one already exists, its read count will be incremented before
+	 * it is returned.
+	 * 
+	 * @param id
+	 *            - the id for the model
+	 * @param inStream
+	 *            - the initial contents of the model
+	 * @param resolver
+	 *            - the URIResolver to use for locating any needed resources
+	 * @return a structured model for the given content, or null if one could
+	 *         not be found or created
+	 * @throws UnsupportedEncodingException
+	 * @throws IOException
+	 *             if the contents can not be read or its detected encoding
+	 *             does not support its contents
+	 * @deprecated - a URI resolver should be automatically created when
+	 *             needed
+	 */
+	public IStructuredModel getModelForRead(String filename, InputStream inStream, URIResolver resolver) throws UnsupportedEncodingException, IOException;
+
+	/**
+	 * This method will not create a new model if it already exists ... if
+	 * force is false. The idea is that a client should call this method once
+	 * with force set to false. If the exception is thrown, then prompt client
+	 * if they want to overwrite.
+	 * 
+	 * @param iFile
+	 * @param force
+	 * @return the new structured model, or 
+	 * @throws ResourceInUse if the given new ID is already in use by a managed model
+	 * @throws CoreException if the file's contents or description can not be read
+	 * @throws IOException if the file's contents can not be read or its detected encoding does not support its contents
+	 * @throws ResourceAlreadyExists if the give file already exists
+	 */
+	IStructuredModel getNewModelForEdit(IFile iFile, boolean force) throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException;
+
+	/**
+	 * This method will not create a new model if it already exists ... if
+	 * force is false. The idea is that a client should call this method once
+	 * with force set to false. If the exception is thrown, then prompt client
+	 * if they want to overwrite.
+	 * 
+	 * @param iFile
+	 * @param force
+	 * @return the new structured model, or 
+	 * @throws ResourceInUse if the given new ID is already in use by a managed model
+	 * @throws CoreException if the file's contents or description can not be read
+	 * @throws IOException if the file's contents can not be read or its detected encoding does not support its contents
+	 * @throws ResourceAlreadyExists if the give file already exists
+	 */
+	IStructuredModel getNewModelForRead(IFile iFile, boolean force) throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException;
+
+	/**
+	 * This function returns the combined "read" and "edit" reference counts
+	 * of underlying model.
+	 * 
+	 * @param id
+	 *            Object The id of the model
+	 * @deprecated - internal information that can be obtained from the model
+	 *             itself
+	 */
+	int getReferenceCount(Object id);
+
+	/**
+	 * This function returns the "edit" reference count of underlying model.
+	 * 
+	 * @param id
+	 *            Object The id of the model
+	 * @deprecated - internal information that can be obtained from the model itself
+	 */
+	int getReferenceCountForEdit(Object id);
+
+	/**
+	 * This function returns the "read" reference count of underlying model.
+	 * 
+	 * @param id
+	 *            Object The id of the model TODO: try to refine the design
+	 *            not to use this function
+	 * @deprecated - internal information that can be obtained from the model itself
+	 */
+	int getReferenceCountForRead(Object id);
+
+	/**
+	 * This function returns true if there are other references to the
+	 * underlying model.
+	 * 
+	 * @param id
+	 *            Object The id of the model
+	 */
+	boolean isShared(Object id);
+
+	/**
+	 * This function returns true if there are other "edit" references to the
+	 * underlying model.
+	 * 
+	 * @param id
+	 *            Object The id of the model
+	 */
+	boolean isSharedForEdit(Object id);
+
+	/**
+	 * This function returns true if there are other "read" references to the
+	 * underlying model.
+	 * 
+	 * @param id
+	 *            Object The id of the model
+	 */
+	boolean isSharedForRead(Object id);
+
+	/**
+	 * @deprecated - not granular enough
+	 * 
+	 * This method can be called to determine if the model manager is within a
+	 * "aboutToChange" and "changed" sequence.
+	 */
+	public boolean isStateChanging();
+
+	/**
+	 * This method changes the id of the model. 
+	 * 
+	 * TODO: try to refine the design
+	 * not to use this function
+	 * 
+	 * @deprecated
+	 */
+	void moveModel(Object oldId, Object newId);
+
+	/**
+	 * This method can be called when the content type of a model changes. It's
+	 * assumed the contentType has already been changed, and this method uses
+	 * the text of the old one, to repopulate the text of the new one. In
+	 * theory, the actual instance could change, (e.g. using 'saveAs' to go
+	 * from xml to dtd), but in practice, the intent of this API is to return
+	 * the same instance, just using different handlers, adapter factories,
+	 * etc.
+	 */
+	IStructuredModel reinitialize(IStructuredModel model) throws IOException;
+
+	/**
+	 * This is similar to the getModel method, except this method does not use
+	 * the cached version, but forces the cached version to be replaced with a
+	 * fresh, unchanged version. Note: this method does not change any
+	 * reference counts. Also, if there is not already a cached version of the
+	 * model, then this call is essentially ignored (that is, it does not put
+	 * a model in the cache) and returns null.
+	 * 
+	 * @deprecated
+	 */
+	IStructuredModel reloadModel(Object id, InputStream inStream) throws UnsupportedEncodingException;
+
+	/**
+	 * Saves the contents of the given structured document to the given file. If
+	 * the document belongs to a managed model, that model will be saved and
+	 * marked as non-dirty.
+	 * 
+	 * @param structuredDocument
+	 *            - the structured document
+	 * @param iFile
+	 *            - the file to save to
+	 * @throws UnsupportedEncodingException
+	 * @throws CoreException if the file's contents or description can not be read
+	 * @throws IOException if the file's contents can not be read or its detected encoding does not support its contents
+	 */
+	void saveStructuredDocument(IStructuredDocument structuredDocument, IFile iFile) throws UnsupportedEncodingException, IOException, CoreException;
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IModelStateListener.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IModelStateListener.java
new file mode 100644
index 0000000..b14e473
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IModelStateListener.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional;
+
+
+
+/**
+ * Interface for those wanting to listen to a model's state changing.
+ */
+public interface IModelStateListener {
+
+	/**
+	 * A model is about to be changed. This typically is initiated by one
+	 * client of the model, to signal a large change and/or a change to the
+	 * model's ID or base Location. A typical use might be if a client might
+	 * want to suspend processing until all changes have been made.
+	 */
+	void modelAboutToBeChanged(IStructuredModel model);
+
+	/**
+	 * Signals that the changes foretold by modelAboutToBeChanged have been
+	 * made. A typical use might be to refresh, or to resume processing that
+	 * was suspended as a result of modelAboutToBeChanged.
+	 */
+	void modelChanged(IStructuredModel model);
+
+	/**
+	 * Notifies that a model's dirty state has changed, and passes that state
+	 * in isDirty. A model becomes dirty when any change is made, and becomes
+	 * not-dirty when the model is saved.
+	 */
+	void modelDirtyStateChanged(IStructuredModel model, boolean isDirty);
+
+	/**
+	 * A modelDeleted means the underlying resource has been deleted. The
+	 * model itself is not removed from model management until all have
+	 * released it. Note: baseLocation is not (necessarily) changed in this
+	 * event, but may not be accurate.
+	 */
+	void modelResourceDeleted(IStructuredModel model);
+
+	/**
+	 * A model has been renamed or copied (as in saveAs..). In the renamed
+	 * case, the two paramenters are the same instance, and only contain the
+	 * new info for id and base location.
+	 */
+	void modelResourceMoved(IStructuredModel oldModel, IStructuredModel newModel);
+
+	void modelAboutToBeReinitialized(IStructuredModel structuredModel);
+
+	void modelReinitialized(IStructuredModel structuredModel);
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/INodeAdapter.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/INodeAdapter.java
new file mode 100644
index 0000000..e88a24f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/INodeAdapter.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional;
+
+/**
+ * This interface allows nodes to be adapted.
+ * 
+ * The main difference between this type of adapter (IAdaptable) and base
+ * adapter is that these adapters are notified of changes.
+ * 
+ * @plannedfor 1.0
+ */
+
+public interface INodeAdapter {
+
+	/**
+	 * The infrastructure calls this method to determine if the adapter is
+	 * appropriate for 'type'. Typically, adapters return true based on
+	 * identity comparison to 'type', but this is not required, that is, the
+	 * decision can be based on complex logic.
+	 * 
+	 */
+	boolean isAdapterForType(Object type);
+
+	/**
+	 * Sent to adapter when notifier changes. Each notifier is responsible for
+	 * defining specific eventTypes, feature changed, etc.
+	 * 
+	 * ISSUE: may be more evolvable if the argument was one big 'notifier
+	 * event' instance.
+	 */
+	void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/INodeAdapterFactory.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/INodeAdapterFactory.java
new file mode 100644
index 0000000..d6a2506
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/INodeAdapterFactory.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional;
+
+/**
+ * INodeNotifiers can be adapted by INodeAdapters. This factory interface
+ * provides a way to provide factories which are invoked by the infrastructure
+ * to manage this process, from creating, to adapting, to releasing, if
+ * required.
+ * 
+ * @plannedfor 1.0
+ * 
+ */
+public interface INodeAdapterFactory {
+
+	/**
+	 * The primary purpose of an adapter factory is to create an adapter and
+	 * associate it with an INodeNotifier. This adapt method Method that
+	 * returns the adapter associated with the given object. The
+	 * implementation of this method should call addAdapter on the adapted
+	 * object with the correct instance of the adapter, if appropriate.
+	 * 
+	 * Note: the instance of the adapter returned may be a singleton or not
+	 * ... depending on the needs of the INodeAdapter ... but in general it is
+	 * recommended for an adapter to be stateless, so the efficiencies of a
+	 * singleton can be gained.
+	 * 
+	 * @param object
+	 *            the node notifier to be adapted
+	 */
+	INodeAdapter adapt(INodeNotifier object);
+
+	/**
+	 * Unlike clone, this method may or may not return the same instance, such
+	 * as in the case where the IAdapterFactory is intended to be a singleton.
+	 * 
+	 * @return an instance of this adapter factory.
+	 */
+	public INodeAdapterFactory copy();
+
+	/**
+	 * isFactoryForType is called by infrastructure to decide if this adapter
+	 * factory is apporiate to use for an adapter request that specifies
+	 * 'type'.
+	 * 
+	 * @param type -
+	 *            same object used to identify/request adapters.
+	 * @return true if factory is appropriate for type, false otherwise.
+	 */
+	boolean isFactoryForType(Object type);
+
+	/**
+	 * release is called by infrastructure when the factory registry is
+	 * released (which is done when a structured model is released). This
+	 * intened for the factory to be allowed to clean up any state information
+	 * it may have.
+	 * 
+	 * Note: while not recommended, due to performance reasons, if individual
+	 * adapters need some cleanup (or need to be released) it is (typically)
+	 * the responsibility of the adapter factory to track them, and initiate
+	 * what ever clean up is needed. In other works, cleanup at the adatper
+	 * level is not provided by infrastructure.
+	 */
+	public void release();
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/INodeNotifier.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/INodeNotifier.java
new file mode 100644
index 0000000..a76fe75
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/INodeNotifier.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional;
+
+
+
+import java.util.Collection;
+
+/**
+ * INodeNotifiers and INodeAdapters form a collaboration that allows clients
+ * to use the typical adapter pattern but with notification added, that is,
+ * client's adapters will be notified when the nodeNotifier changes.
+ * 
+ * @plannedfor 1.0
+ */
+
+public interface INodeNotifier {
+
+	/**
+	 * The change represents a non-structural change, sent to node notifier's
+	 * parent.
+	 */
+	static final int CHANGE = 1;
+	/**
+	 * The change represents an add event.
+	 */
+	static final int ADD = 2;
+
+	/**
+	 * The change represents a remove event.
+	 */
+	static final int REMOVE = 3;
+
+	/**
+	 * The change represents a structural change, sent to least-common parent
+	 * of node notifiers involved in the structural change
+	 */
+	static final int STRUCTURE_CHANGED = 4;
+
+	/**
+	 * The change represents a notification to parent notifier than its
+	 * contents have changed.
+	 */
+	static final int CONTENT_CHANGED = 5;
+
+
+	/**
+	 * NOT API: these strings are for printing, such as during debugging
+	 */
+	static final String[] EVENT_TYPE_STRINGS = new String[]{"undefined", "CHANGE", "ADD", "REMOVE", "STRUCTURE_CHANGED", "CONTENT_CHANGED"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
+
+
+	/**
+	 * Add an adapter of this notifier.
+	 * 
+	 * @param adapter
+	 *            the adapter to be added
+	 * 
+	 */
+	void addAdapter(INodeAdapter adapter);
+
+	/**
+	 * Return an exisiting adapter of type "type" or if none found create a
+	 * new adapter using a registered adapter factory
+	 */
+	INodeAdapter getAdapterFor(Object type);
+
+	/**
+	 * Return a read-only Collection of the Adapters to this notifier.
+	 * 
+	 * @return collection of adapters.
+	 */
+	Collection getAdapters();
+
+	/**
+	 * Return an exisiting adapter of type "type" or null if none found
+	 */
+	INodeAdapter getExistingAdapter(Object type);
+
+	/**
+	 * sent to adapter when its nodeNotifier changes.
+	 */
+	void notify(int eventType, Object changedFeature, Object oldValue, Object newValue, int pos);
+
+	/**
+	 * Remove an adapter of this notifier. If the adapter does not exist for
+	 * this node notifier, this request is ignored.
+	 * 
+	 * @param adapter
+	 *            the adapter to remove
+	 */
+	void removeAdapter(INodeAdapter adapter);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IStructuredModel.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IStructuredModel.java
new file mode 100644
index 0000000..8669019
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IStructuredModel.java
@@ -0,0 +1,419 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2011 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingRule;
+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
+import org.eclipse.wst.sse.core.internal.model.FactoryRegistry;
+import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceAlreadyExists;
+import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceInUse;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager;
+import org.eclipse.wst.sse.core.internal.util.URIResolver;
+
+
+/**
+ * IStructuredModels are mainly interesting by their extensions and
+ * implementers. The main purposed of this abstraction is to provide a common
+ * means to manage models that have an associated structured document.
+ * 
+ * <p>
+ * TODO: this interface needs ton of cleanup!
+ * </p>
+ * 
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IStructuredModel extends IAdaptable {
+
+
+	/**
+	 * This API allows clients to declare that they are about to make a
+	 * "large" change to the model. This change might be in terms of content
+	 * or it might be in terms of the model id or base location.
+	 * 
+	 * Note that in the case of embedded calls, notification to listeners is
+	 * sent only once.
+	 * 
+	 * Note that the client who is making these changes has the responsibility
+	 * to restore the model's state once finished with the changes. See
+	 * getMemento and restoreState.
+	 * 
+	 * The method isModelStateChanging can be used by a client to determine if
+	 * the model is already in a change sequence.
+	 * 
+	 * This method is a matched pair to changedModel, and must be called
+	 * before changedModel. A client should never call changedModel without
+	 * calling aboutToChangeModel first nor call aboutToChangeModel without
+	 * calling changedModel later from the same Thread.
+	 */
+	void aboutToChangeModel();
+
+	void addModelLifecycleListener(IModelLifecycleListener listener);
+
+	void addModelStateListener(IModelStateListener listener);
+
+	/**
+	 * Begin recording undo transactions.
+	 */
+	void beginRecording(Object requester);
+
+	/**
+	 * Begin recording undo transactions.
+	 */
+	void beginRecording(Object requester, int cursorPosition, int selectionLength);
+
+	/**
+	 * Begin recording undo transactions.
+	 */
+	void beginRecording(Object requester, String label);
+
+	/**
+	 * Begin recording undo transactions.
+	 */
+	void beginRecording(Object requester, String label, int cursorPosition, int selectionLength);
+
+	/**
+	 * Begin recording undo transactions.
+	 */
+	void beginRecording(Object requester, String label, String description);
+
+	/**
+	 * Begin recording undo transactions.
+	 */
+	void beginRecording(Object requester, String label, String description, int cursorPosition, int selectionLength);
+
+	/**
+	 * This API allows a client controlled way of notifying all ModelEvent
+	 * listeners that the model has been changed. This method is a matched
+	 * pair to aboutToChangeModel, and must be called after aboutToChangeModel
+	 * ... or some listeners could be left waiting indefinitely for the
+	 * changed event. So, its suggested that changedModel always be in a
+	 * finally clause. Likewise, a client should never call changedModel
+	 * without calling aboutToChangeModel first.
+	 * 
+	 * In the case of embedded calls, the notification is just sent once.
+	 * 
+	 */
+	void changedModel();
+
+	long computeModificationStamp(IResource resource);
+
+	/**
+	 * @deprecated
+	 * @see IModelManager#copyModelForEdit(String, String)
+	 */
+	IStructuredModel copy(String id) throws ResourceInUse, ResourceAlreadyExists;
+
+	/**
+	 * Disable undo management.
+	 * 
+	 * @deprecated - the ability to enable and disable Undo management for the
+	 *             model cannot be guaranteed as it implicitly requires
+	 *             knowledge of the underlying undo/redo implementation
+	 */
+	void disableUndoManagement();
+
+	/**
+	 * Enable undo management.
+	 * 
+	 * @deprecated - the ability to enable and disable Undo management for the
+	 *             model cannot be guaranteed as it implicitly requires
+	 *             knowledge of the underlying undo/redo implementation
+	 */
+	void enableUndoManagement();
+
+	/**
+	 * End recording undo transactions.
+	 */
+	void endRecording(Object requester);
+
+	/**
+	 * End recording undo transactions.
+	 */
+	void endRecording(Object requester, int cursorPosition, int selectionLength);
+
+	/**
+	 * This is a client-defined value for what that client (and/or loader)
+	 * considers the "base" of the structured model. Frequently the location
+	 * is either a workspace root-relative path of a workspace resource or an
+	 * absolute location in the local file system.
+	 * 
+	 * @return the base location of the model or <code>null</code> when one
+	 *         has not been set, such as in models resulting from calling
+	 *         {@link IModelManager#createNewInstance(IStructuredModel)}
+	 */
+	String getBaseLocation();
+
+	/**
+	 * @return The associated content type identifier (String) for this model.
+	 *         This value may be more accurate than the content type against
+	 *         which the model handler was registered.
+	 *         
+	 *         @see IModelHandler#getAssociatedContentTypeId()
+	 */
+	String getContentTypeIdentifier();
+
+	/**
+	 * 
+	 * @return The model's FactoryRegistry. A model is not valid without one.
+	 */
+	FactoryRegistry getFactoryRegistry();
+
+	/**
+	 * The id is the id that the model manager uses to identify this model
+	 */
+	String getId();
+
+	/**
+	 * @param offset
+	 *            a text offset within the structured document
+	 * @return an IndexedRegion containing this offset or null if one could
+	 *         not be found
+	 */
+	IndexedRegion getIndexedRegion(int offset);
+
+	/**
+	 * @return the model's handler
+	 */
+	IModelHandler getModelHandler();
+
+	IModelManager getModelManager();
+
+	/**
+	 * @param id
+	 *            Object The id of the model TODO: try to refine the design
+	 *            not to use this function
+	 * 
+	 * @return the reference count of underlying model
+	 */
+	int getReferenceCount();
+
+	/**
+	 * This function returns the edit-responsible reference count of
+	 * underlying model.
+	 * 
+	 * @param id
+	 *            Object The id of the model TODO: try to refine the design
+	 *            not to use this function
+	 */
+	int getReferenceCountForEdit();
+
+	/**
+	 * This function returns the reader reference count of underlying model.
+	 * 
+	 * @param id
+	 *            Object The id of the model TODO: try to refine the design
+	 *            not to use this function
+	 */
+	int getReferenceCountForRead();
+
+	Object getReinitializeStateData();
+
+	/**
+	 * Get URI resolution helper
+	 * 
+	 * @deprecated - use org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin.createResolver(*) instead
+	 */
+	URIResolver getResolver();
+
+	IStructuredDocument getStructuredDocument();
+
+	/**
+	 * modification date of underlying resource, when this model was open, or
+	 * last saved. (Note: for this version, the client must manage the
+	 * accuracy of this data)
+	 */
+	long getSynchronizationStamp();
+
+	/**
+	 * Get undo manager.
+	 */
+	IStructuredTextUndoManager getUndoManager();
+
+	/**
+	 * 
+	 */
+	boolean isDirty();
+
+	/**
+	 * This method can be called to determine if the model is within a
+	 * "aboutToChange" and "changed" sequence.
+	 */
+	public boolean isModelStateChanging();
+
+	/**
+	 * 
+	 */
+	boolean isNew();
+
+	boolean isReinitializationNeeded();
+
+	/**
+	 * This is a combination of if the model is dirty and if the model is
+	 * shared for write access. The last writer as the responsibility to be
+	 * sure the user is prompted to save.
+	 */
+	public boolean isSaveNeeded();
+
+	/**
+	 * This function returns true if either isSharedForRead or isSharedForEdit
+	 * is true.
+	 */
+	boolean isShared();
+
+	/**
+	 * This function returns true if there are other references to the
+	 * underlying model.
+	 */
+	boolean isSharedForEdit();
+
+	/**
+	 * This function returns true if there are other references to the
+	 * underlying model.
+	 */
+	boolean isSharedForRead();
+
+	/**
+	 * newInstance is similar to clone, except that the newInstance contains
+	 * no content. Its purpose is so clients can get a temporary, unmanaged,
+	 * model of the same "type" as the original. Note: the client may still
+	 * need to do some initialization of the model returned by newInstance,
+	 * depending on desired use. For example, the only factories in the
+	 * newInstance are those that would be normally be created for a model of
+	 * the given contentType. Others are not copied automatically, and if
+	 * desired, should be added by client.
+	 */
+	IStructuredModel newInstance() throws IOException;
+
+	/**
+	 * Performs a reinitialization procedure. For this model. Note for future:
+	 * there may be a day where the model returned from this method is a
+	 * different instance than the instance it was called on. This will occur
+	 * when there is full support for "save as" type functions, where the
+	 * model could theoretically change completely.
+	 */
+	IStructuredModel reinit() throws IOException;
+
+	/**
+	 * This function allows the model to free up any resources it might be
+	 * using. In particular, itself, as stored in the IModelManager.
+	 * 
+	 */
+	void releaseFromEdit();
+
+	/**
+	 * This function allows the model to free up any resources it might be
+	 * using. In particular, itself, as stored in the IModelManager.
+	 * 
+	 */
+	void releaseFromRead();
+
+	/**
+	 * This function replenishes the model with the resource without saving
+	 * any possible changes. It is used when one editor may be closing, and
+	 * specifically says not to save the model, but another "display" of the
+	 * model still needs to hang on to some model, so needs a fresh copy.
+	 * 
+	 * Only valid for use with managed models.
+	 */
+	IStructuredModel reload(InputStream inputStream) throws IOException;
+
+	void removeModelLifecycleListener(IModelLifecycleListener listener);
+
+	void removeModelStateListener(IModelStateListener listener);
+
+	/**
+	 * A method that modifies the model's synchronization stamp to match the
+	 * resource. Turns out there's several ways of doing it, so this ensures a
+	 * common algorithm.
+	 */
+	void resetSynchronizationStamp(IResource resource);
+
+	void resourceDeleted();
+
+	void resourceMoved(IStructuredModel newModel);
+
+	void save() throws UnsupportedEncodingException, IOException, CoreException;
+
+	/**
+	 * @deprecated - will save according to the encoding priorities specified for the IFile 
+	 */
+	void save(EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException;
+
+	void save(IFile iFile) throws UnsupportedEncodingException, IOException, CoreException;
+
+	/**
+	 * @deprecated - will save according to the encoding priorities specified for the IFile 
+	 */
+	void save(IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException;
+
+	void save(OutputStream outputStream) throws UnsupportedEncodingException, IOException, CoreException;
+
+	/**
+	 * Sets the base location of this model to the new value, also updating
+	 * the value in its URI resolution helper if one is present.
+	 * 
+	 * @param newBaseLocation
+	 */
+	void setBaseLocation(String newBaseLocation);
+
+	public void setDirtyState(boolean dirtyState);
+
+	void setFactoryRegistry(FactoryRegistry registry);
+
+	/**
+	 * The id is the id that the model manager uses to identify this model
+	 */
+	void setId(String id) throws ResourceInUse;
+
+	void setModelHandler(IModelHandler modelHandler);
+
+	void setModelManager(IModelManager modelManager);
+
+	public void setNewState(boolean newState);
+
+	/**
+	 * Sets a "flag" that reinitialization is needed.
+	 */
+	void setReinitializeNeeded(boolean b);
+
+	/**
+	 * Holds any data that the reinitialization procedure might find useful in
+	 * reinitializing the model. This is handy, since the reinitialization may
+	 * not take place at once, and some "old" data may be needed to properly
+	 * undo previous settings. Note: the parameter was intentionally made to
+	 * be of type 'Object' so different models can use in different ways.
+	 */
+	void setReinitializeStateData(Object object);
+
+	/**
+	 * Set the URI resolution helper
+	 */
+	void setResolver(URIResolver uriResolver);
+
+	void setStructuredDocument(IStructuredDocument structuredDocument);
+
+	/**
+	 * Set undo manager.
+	 */
+	void setUndoManager(IStructuredTextUndoManager undoManager);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IndexedRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IndexedRegion.java
new file mode 100644
index 0000000..a9e9538
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/IndexedRegion.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional;
+
+
+
+/**
+ * This type is used to indicate positions and lengths in source. Notice that
+ * while getEndOffset and getLength are redundant, given that
+ * 
+ * <pre>
+ * <code>
+ *          getEndOffset() == getStartOffset() + getLength(); 
+ * </code>
+ * </pre>
+ * 
+ * we provide (require) both since in some cases implementors may be able to
+ * provide one or the other more efficiently.
+ * 
+ * Note: it is not part of the API contract that implementors of IndexedRegion --
+ * as a whole collection for a particular source -- must completely cover the
+ * original source. They currently often do, so thought I'd mention explicitly
+ * this may not always be true.
+ * 
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IndexedRegion {
+
+	/**
+	 * Can be used to test if the indexed regions contains the test position.
+	 * 
+	 * @param testPosition
+	 * @return true if test position is greater than or equal to start offset
+	 *         and less than start offset plus length.
+	 */
+	boolean contains(int testPosition);
+
+	/**
+	 * Can be used to get end offset of source text, relative to beginning of
+	 * documnt. Implementers should return -1 if, or some reason, the region
+	 * is not valid.
+	 * 
+	 * @return endoffset
+	 */
+	int getEndOffset();
+
+	/**
+	 * Can be used to get source postion of beginning of indexed region.
+	 * Implementers should return -1 if, or some reason, the region is not
+	 * valid.
+	 * 
+	 * @return int position of start of index region.
+	 */
+	int getStartOffset();
+
+	/**
+	 * Can be used to get the length of the source text. Implementers should
+	 * return -1 if, or some reason, the region is not valid.
+	 * 
+	 * @return int position of length of index region.
+	 */
+	int getLength();
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/StructuredModelManager.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/StructuredModelManager.java
new file mode 100644
index 0000000..61e0718
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/StructuredModelManager.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2011 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.wst.sse.core.internal.provisional;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.wst.sse.core.internal.SSECorePlugin;
+import org.eclipse.wst.sse.core.internal.model.ModelManagerImpl;
+import org.osgi.framework.Bundle;
+
+/**
+ * Class to allow access to ModelManager. Not intended to be subclassed.
+ * 
+ * @deprecated - use {@link org.eclipse.wst.sse.core.StructuredModelManager} instead
+ */
+final public class StructuredModelManager {
+	/**
+	 * Do not allow instances to be created.
+	 */
+	private StructuredModelManager() {
+		super();
+	}
+
+	/**
+	 * Provides access to the instance of IModelManager. Returns null if model
+	 * manager can not be created or is not valid (such as, when workbench is
+	 * shutting down).
+	 * 
+	 * @return IModelManager - returns the one model manager for structured
+	 *         model
+	 * @deprecated - use the one that is in
+	 *             org.eclipse.wst.sse.core.StructuredModelManager
+	 */
+	public static IModelManager getModelManager() {
+		boolean isReady = false;
+		IModelManager modelManager = null;
+		while (!isReady) {
+			Bundle localBundle = Platform.getBundle(SSECorePlugin.ID);
+			int state = localBundle.getState();
+			if (state == Bundle.ACTIVE) {
+				isReady = true;
+				// getInstance is a synchronized static method.
+				modelManager = ModelManagerImpl.getInstance();
+			}
+			else if (state == Bundle.STARTING) {
+				try {
+					Thread.sleep(100);
+				}
+				catch (InterruptedException e) {
+					// ignore, just loop again
+				}
+			}
+			else if (state == Bundle.STOPPING || state == Bundle.UNINSTALLED) {
+				isReady = true;
+				modelManager = null;
+			}
+			else {
+				// not sure about other states, 'resolved', 'installed'
+				isReady = true;
+				modelManager = null;
+			}
+		}
+		return modelManager;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/document/IEncodedDocument.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/document/IEncodedDocument.java
new file mode 100644
index 0000000..2d64715
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/document/IEncodedDocument.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.document;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+
+/**
+ * This interface is strictly to define important "document properties" not
+ * found in IDocument, but not central to "StructuredDocument".
+ * 
+ * Its not to be be implmented by clients.
+ * 
+ * @plannedfor 1.0
+ */
+
+public interface IEncodedDocument extends IDocument {
+
+	/**
+	 * Returns the encoding memento for this document.
+	 * 
+	 * @return the encoding memento for this document.
+	 */
+	EncodingMemento getEncodingMemento();
+
+	/**
+	 * Returns the preferred line delimiter for this document.
+	 */
+	String getPreferredLineDelimiter();
+
+	/**
+	 * Sets the encoding memento for this document.
+	 * 
+	 * Is not to be called by clients, only document creation classes.
+	 * 
+	 * @param localEncodingMemento
+	 */
+	void setEncodingMemento(EncodingMemento localEncodingMemento);
+
+	/**
+	 * Sets the preferredLineDelimiter. Is not to be called by clients, only
+	 * document creation classes.
+	 * 
+	 * @param probableLineDelimiter
+	 */
+	void setPreferredLineDelimiter(String probableLineDelimiter);
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/document/IStructuredDocumentProposed.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/document/IStructuredDocumentProposed.java
new file mode 100644
index 0000000..0c0f47d
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/document/IStructuredDocumentProposed.java
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.document;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.Position;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.provisional.events.NewDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList;
+
+
+/**
+ * A IStructuredDocument is a collection of StructuredDocumentRegions. It's
+ * often called a "flat model" because its does contain some structural
+ * information, but not very much, usually, at most, a few levels of
+ * containment.
+ * 
+ * Clients should not implement.
+ * 
+ * @deprecated - was never used
+ */
+public interface IStructuredDocumentProposed extends IDocument, IDocumentExtension, IAdaptable {
+
+	/**
+	 * The document changing listeners receives the same events as the
+	 * document listeners, but the difference is the timing and
+	 * synchronization of data changes and notifications.
+	 */
+	void addDocumentChangingListener(IDocumentListener listener);
+
+	/**
+	 * this API ensures that any portion of the document within startOff to
+	 * length is not readonly (that is, that its editable). Note that if the
+	 * range overlaps with other readonly regions, those other readonly
+	 * regions will be adjusted.
+	 * 
+	 * @param startOffset
+	 * @param length
+	 */
+	void clearReadOnly(int startOffset, int length);
+
+	/**
+	 * returns true if any portion of startOffset to length is readonly
+	 * 
+	 * @param startOffset
+	 * @param length
+	 * @return
+	 */
+	boolean containsReadOnly(int startOffset, int length);
+
+	/**
+	 * Returns the region contained by offset.
+	 * 
+	 * @param offset
+	 * @return
+	 */
+	IStructuredDocumentRegion getRegionAtCharacterOffset(int offset);
+
+	/**
+	 * Resturns a list of the structured document regions.
+	 * 
+	 * Note: possibly expensive call, not to be used casually.
+	 * 
+	 * @return a list of the structured document regions.
+	 */
+	IStructuredDocumentRegionList getRegionList();
+
+
+	/**
+	 * Returns the text of this document.
+	 * 
+	 * Same as 'get' in super class, added for descriptiveness.
+	 * 
+	 * @return the text of this document.
+	 */
+	String getText();
+
+	/**
+	 * causes that portion of the document from startOffset to length to be
+	 * marked as readonly. Note that if this range overlaps with some other
+	 * region with is readonly, the regions are effectivly combined.
+	 * 
+	 * @param startOffset
+	 * @param length
+	 */
+	void makeReadOnly(int startOffset, int length);
+
+	/**
+	 * newInstance is similar to clone, except it contains no data. One
+	 * important thing to duplicate is the parser, with the parser correctly
+	 * "cloned", including its tokeninzer, block tags, etc.
+	 * 
+	 * NOTE: even after obtaining a 'newInstance' the client may have to do
+	 * some initialization, for example, it may need to add its own model
+	 * listeners. Or, as another example, if the IStructuredDocument has a
+	 * parser of type StructuredDocumentRegionParser, then the client may need
+	 * to add its own StructuredDocumentRegionHandler to that parser, if it is
+	 * in fact needed.
+	 */
+	IStructuredDocumentProposed newInstance();
+
+	/**
+	 * The document changing listeners receives the same events as the
+	 * document listeners, but the difference is the timing and
+	 * synchronization of data changes and notifications.
+	 */
+	void removeDocumentChangingListener(IDocumentListener listener);
+
+	/**
+	 * One of the APIs to manipulate the IStructuredDocument.
+	 * 
+	 * replaceText replaces the text from oldStart to oldEnd with the new text
+	 * found in the requestedChange string. If oldStart and oldEnd are equal,
+	 * it is an insertion request. If requestedChange is null (or empty) it is
+	 * a delete request. Otherwise it is a replace request.
+	 * 
+	 * Similar to 'replace' in super class.
+	 */
+	StructuredDocumentEvent replaceText(Object requester, int oldStart, int replacementLength, String requestedChange);
+
+	/**
+	 * Note, same as replaceText API, but will allow readonly areas to be
+	 * replaced. This method is not to be called by clients, only
+	 * infrastructure. For example, one case where its ok is with undo
+	 * operations (since, presumably, if user just did something that
+	 * happended to involve some inserting readonly text, they should normally
+	 * be allowed to still undo that operation. There might be other cases
+	 * where its used to give the user a choice, e.g. "you are about to
+	 * overwrite read only portions, do you want to continue".
+	 */
+	StructuredDocumentEvent overrideReadOnlyreplaceText(Object requester, int oldStart, int replacementLength, String requestedChange);
+
+	/**
+	 * One of the APIs to manipulate the IStructuredDocument in terms of Text.
+	 * 
+	 * The setText method replaces all text in the model.
+	 * 
+	 * @param requester -
+	 *            the object requesting the document be created.
+	 * @param allText -
+	 *            all the text of the document.
+	 * @return NewDocumentEvent - besides causing this event to be sent to
+	 *         document listeners, the event is returned.
+	 */
+	NewDocumentEvent setText(Object requester, String allText);
+
+	/**
+	 * Returns the encoding memento for this document.
+	 * 
+	 * @return the encoding memento for this document.
+	 */
+	EncodingMemento getEncodingMemento();
+
+	/**
+	 * Returns the line delimiter detected when this document was read from
+	 * storage.
+	 * 
+	 * @return line delimiter detected when this document was read from
+	 *         storage.
+	 */
+	String getDetectedLineDelimiter();
+
+	/**
+	 * Sets the encoding memento for this document.
+	 * 
+	 * Is not to be called by clients, only document creation classes.
+	 * 
+	 * @param localEncodingMemento
+	 */
+	void setEncodingMemento(EncodingMemento localEncodingMemento);
+
+	/**
+	 * Sets the detected line delimiter when the document was read. Is not to
+	 * be called by clients, only document creation classes.
+	 * 
+	 * @param probableLineDelimiter
+	 */
+	void setDetectedLineDelimiter(String probableLineDelimiter);
+
+	/**
+	 * This function provides a way for clients to compare a string with a
+	 * region of the documnet, without having to retrieve (create) a string
+	 * from the document, thus more efficient of lots of comparisons being
+	 * done.
+	 * 
+	 * @param ignoreCase -
+	 *            if true the characters are compared based on identity. If
+	 *            false, the string are compared with case accounted for.
+	 * @param testString -
+	 *            the string to compare.
+	 * @param documentOffset -
+	 *            the document in the offset to start the comparison.
+	 * @param length -
+	 *            the length in the document to compare (Note: technically,
+	 *            clients could just provide the string, and we could infer
+	 *            the length from the string supplied, but this leaves every
+	 *            client to correctly not even ask us if the the string length
+	 *            doesn't match the expected length, so this is an effort to
+	 *            maximize performance with correct code.
+	 * @return true if matches, false otherwise.
+	 */
+	boolean stringMatches(boolean ignoreCase, String testString, int documentOffset, int length);
+	
+	Position createPosition(int offset, String category, String type);
+	
+	Position createPosition(int offset, int length, String category, String type);
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/AboutToBeChangedEvent.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/AboutToBeChangedEvent.java
new file mode 100644
index 0000000..e549692
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/AboutToBeChangedEvent.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.events;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+/**
+ * This event is send to structured document listeners. It is perfectly
+ * analagous to its corresponding jface DocumentEvent and is provided simply
+ * to allow clients to distinguish the source of the event.
+ * 
+ * @plannedfor 1.0
+ */
+public class AboutToBeChangedEvent extends StructuredDocumentEvent {
+
+
+	/**
+	 * Creates an instance of this event.
+	 * 
+	 * @param document
+	 *            document involved in the change
+	 * @param originalRequester
+	 *            source of original request
+	 * @param changes
+	 *            the text changes
+	 * @param offset
+	 *            offset of request
+	 * @param lengthToReplace
+	 *            amount, if any, of replaced text
+	 */
+	public AboutToBeChangedEvent(IStructuredDocument document, Object originalRequester, String changes, int offset, int lengthToReplace) {
+		super(document, originalRequester, changes, offset, lengthToReplace);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/IModelAboutToBeChangedListener.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/IModelAboutToBeChangedListener.java
new file mode 100644
index 0000000..df44547
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/IModelAboutToBeChangedListener.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.events;
+
+
+
+/**
+ * Clients can implement this interface, and register with the
+ * structuredDocument using addAboutToBeChangedListner to be notified that the
+ * structuredDocument is about to be changed, but hasn't been changed at the
+ * time this event is fired.
+ */
+public interface IModelAboutToBeChangedListener {
+
+	void modelAboutToBeChanged(AboutToBeChangedEvent structuredDocumentEvent);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/IStructuredDocumentListener.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/IStructuredDocumentListener.java
new file mode 100644
index 0000000..26535af
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/IStructuredDocumentListener.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.events;
+
+/**
+ * @deprecated will be removed since we now subclass DocumentEvent.
+ */
+
+public interface IStructuredDocumentListener {
+
+	public void newModel(NewDocumentEvent structuredDocumentEvent);
+
+	public void noChange(NoChangeEvent structuredDocumentEvent);
+
+	public void nodesReplaced(StructuredDocumentRegionsReplacedEvent structuredDocumentEvent);
+
+	public void regionChanged(RegionChangedEvent structuredDocumentEvent);
+
+	public void regionsReplaced(RegionsReplacedEvent structuredDocumentEvent);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/NewDocumentContentEvent.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/NewDocumentContentEvent.java
new file mode 100644
index 0000000..038db77
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/NewDocumentContentEvent.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.events;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+/**
+ * The NewDocumentContentEvent is fired when an instance of a
+ * IStructuredDocument replaces all of its text.
+ * 
+ * ISSUE: not currently used, but there's still some efficiencies to be had so
+ * plan to implement.
+ * 
+ * @plannedfor 1.0
+ */
+public class NewDocumentContentEvent extends NewDocumentEvent {
+	/**
+	 * Creates an instance of this event.
+	 * 
+	 * @param document
+	 *            the document being changed
+	 * @param originalRequester
+	 *            the original requester of the change
+	 */
+	public NewDocumentContentEvent(IStructuredDocument document, Object originalRequester) {
+		super(document, originalRequester);
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/NewDocumentEvent.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/NewDocumentEvent.java
new file mode 100644
index 0000000..fe9a73a
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/NewDocumentEvent.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.events;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+/**
+ * The NewDocumentEvent is fired when an instance of a IStructuredDocument
+ * sets or replaces all of its text.
+ * 
+ * ISSUE: need to change so this is used for 'set' only.
+ * 
+ * @plannedfor 1.0
+ */
+public class NewDocumentEvent extends StructuredDocumentEvent {
+
+
+	/**
+	 * Creates a new instance of the NewDocumentEvent.
+	 * 
+	 * @param document
+	 *            being changed
+	 * @param originalRequester
+	 *            source of request
+	 */
+	public NewDocumentEvent(IStructuredDocument document, Object originalRequester) {
+		super(document, originalRequester);
+	}
+
+	/**
+	 * This returns the length of the new document.
+	 * 
+	 * @return int returns the length of the new document.
+	 */
+	public int getLength() {
+		return getStructuredDocument().getLength();
+	}
+
+	/**
+	 * This doesn't mean quite the same thing as the IStructuredDocument
+	 * Events in the super class. It always will return zero.
+	 * 
+	 * @return int for a newDocument, the offset of is always 0
+	 */
+	public int getOffset() {
+		return 0;
+	}
+
+	/**
+	 * For a new document, the text involved is the complete text.
+	 * 
+	 * @return String the text that is the complete text of the documnet.
+	 */
+	public String getText() {
+		String results = getStructuredDocument().getText();
+		return results;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/NoChangeEvent.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/NoChangeEvent.java
new file mode 100644
index 0000000..d5004bc
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/NoChangeEvent.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.events;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+/**
+ * This event is sent if, after analysis, it is found there is no reason to
+ * change the structuredDocument. This might occur, for example, if someone
+ * pastes in the exact same text that they are replacing, or if someone tries
+ * to change a read-only region.
+ * 
+ * This might be important, for example, if some state variables are set on an
+ * "about the change" event. then if there is no change (i.e.no other event is
+ * fired), those state variables could reset, or whatever, upon receiving this
+ * event.
+ * 
+ * @plannedfor 1.0
+ */
+public class NoChangeEvent extends StructuredDocumentEvent {
+	/**
+	 * NO_CONTENT_CHANGE means that a some text was requested to be replaced
+	 * with identical text, so no change is actually done.
+	 */
+	public final static int NO_CONTENT_CHANGE = 2;
+	/**
+	 * NO_EVENT is used in rare error conditions, when, basically, a request
+	 * to change the document is made before the previous request has
+	 * completed. This event to used so aboutToChange/Changed cycles can
+	 * complete as required, but the document is most likely not modified as
+	 * expected.
+	 */
+	public final static int NO_EVENT = 8;
+	/**
+	 * READ_ONLY_STATE_CHANGE means that the "read only" state of the text was
+	 * changed, not the content itself.
+	 */
+	public final static int READ_ONLY_STATE_CHANGE = 4;
+
+	/**
+	 * set to one of the above detailed reasons for why no change was done.
+	 */
+	public int reason = 0;
+
+	/**
+	 * NoChangeEvent constructor. This event can occur if there was a request
+	 * to modify a document or its properties, but there as not really is no
+	 * change to a document's content.
+	 * 
+	 * @param source
+	 * @param originalSource
+	 *            java.lang.Object
+	 * @param changes
+	 *            java.lang.String
+	 * @param offset
+	 *            int
+	 * @param lengthToReplace
+	 *            int
+	 */
+	public NoChangeEvent(IStructuredDocument source, Object originalSource, String changes, int offset, int lengthToReplace) {
+		super(source, originalSource, changes, offset, lengthToReplace);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/RegionChangedEvent.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/RegionChangedEvent.java
new file mode 100644
index 0000000..29d4381
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/RegionChangedEvent.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.events;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+
+/**
+ * This event is used when a document region changes in a non-structural way.
+ * Non-structural, that is, as far as the IStructuredDocument is concerned.
+ * The whole region, along with the new text is sent, just in case a listener
+ * (e.g. a tree model) might make its own determination of what to do, and
+ * needs the whole region to act appropriately.
+ * 
+ * Note: users should not make assumptions about whether the region is
+ * literally the same instance or not -- it is currently a different instance
+ * that is identical to the old except for the changed region, but this
+ * implementation may change.
+ * 
+ * @plannedfor 1.0
+ */
+public class RegionChangedEvent extends StructuredDocumentEvent {
+	private ITextRegion fChangedRegion;
+	private IStructuredDocumentRegion fStructuredDocumentRegion;
+
+	/**
+	 * Creates instance of a RegionChangedEvent.
+	 * 
+	 * @param document
+	 *            the document being changed.
+	 * @param originalRequester
+	 *            the object making the request for the change.
+	 * @param structuredDocumentRegion
+	 *            the containing region
+	 * @param changedRegion
+	 *            the region that has changed.
+	 * @param changes
+	 *            the string representing the change.
+	 * @param offset
+	 *            the offset of the change.
+	 * @param lengthToReplace
+	 *            the length specified to be replaced.
+	 */
+	public RegionChangedEvent(IStructuredDocument document, Object originalRequester, IStructuredDocumentRegion structuredDocumentRegion, ITextRegion changedRegion, String changes, int offset, int lengthToReplace) {
+		super(document, originalRequester, changes, offset, lengthToReplace);
+		fStructuredDocumentRegion = structuredDocumentRegion;
+		fChangedRegion = changedRegion;
+	}
+
+
+	/**
+	 * Returns the text region changed.
+	 * 
+	 * @return the text region changed
+	 */
+	public ITextRegion getRegion() {
+		return fChangedRegion;
+	}
+
+
+	/**
+	 * Returns the document region changed.
+	 * 
+	 * @return the document region changed
+	 */
+	public IStructuredDocumentRegion getStructuredDocumentRegion() {
+		return fStructuredDocumentRegion;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/RegionsReplacedEvent.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/RegionsReplacedEvent.java
new file mode 100644
index 0000000..21a2e4f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/RegionsReplacedEvent.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.events;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+
+/**
+ * This event is used when a node's regions change, but the document region
+ * itself doesn't. This says nothing about the semantics of the document
+ * region, that may still have changed. Also, its assumed/required that all
+ * the regions are replaced (even those that may not have changed).
+ * 
+ * @plannedfor 1.0
+ */
+public class RegionsReplacedEvent extends StructuredDocumentEvent {
+	private ITextRegionList fNewRegions;
+	private ITextRegionList fOldRegions;
+	private IStructuredDocumentRegion fStructuredDocumentRegion;
+
+	/**
+	 * Creates an instance of the RegionsReplacedEvent.
+	 * 
+	 * @param document -
+	 *            document being changed.
+	 * @param originalRequester -
+	 *            requester of the change.
+	 * @param structuredDocumentRegion -
+	 *            the region containing the change.
+	 * @param oldRegions -
+	 *            the old Regions being replaced.
+	 * @param newRegions -
+	 *            the new regions being added.
+	 * @param changes -
+	 *            the String representing the change.
+	 * @param offset -
+	 *            the offset of the change.
+	 * @param lengthToReplace -
+	 *            the length of text to replace.
+	 */
+	public RegionsReplacedEvent(IStructuredDocument document, Object originalRequester, IStructuredDocumentRegion structuredDocumentRegion, ITextRegionList oldRegions, ITextRegionList newRegions, String changes, int offset, int lengthToReplace) {
+		super(document, originalRequester, changes, offset, lengthToReplace);
+		fStructuredDocumentRegion = structuredDocumentRegion;
+		fOldRegions = oldRegions;
+		fNewRegions = newRegions;
+	}
+
+	/**
+	 * Returns the new text regions.
+	 * 
+	 * @return the new text regions.
+	 */
+	public ITextRegionList getNewRegions() {
+		return fNewRegions;
+	}
+
+	/**
+	 * Returns the old text regions.
+	 * 
+	 * @return the old text regions.
+	 */
+	public ITextRegionList getOldRegions() {
+		return fOldRegions;
+	}
+
+	/**
+	 * Returns the structured document region.
+	 * 
+	 * @return the structured document region.
+	 */
+	public IStructuredDocumentRegion getStructuredDocumentRegion() {
+		return fStructuredDocumentRegion;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/StructuredDocumentEvent.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/StructuredDocumentEvent.java
new file mode 100644
index 0000000..e3930ff
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/StructuredDocumentEvent.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.events;
+
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+
+/**
+ * IStructuredDocument events are generated by the IStructuredDocument, after
+ * the IStructuredDocument acts on a request. Not intended to be instantiated,
+ * except by subclasses in infrastructure. Not intended to be subclassed by
+ * clients.
+ * 
+ * @plannedfor 1.0
+ */
+public abstract class StructuredDocumentEvent extends DocumentEvent {
+	private String fDeletedText;
+	private Object fOriginalRequester;
+
+	/**
+	 * There is no public null-arg version of this constructor.
+	 */
+	private StructuredDocumentEvent() {
+		super();
+	}
+
+	/**
+	 * We assume (and require) that an IStructuredDocument's are always the
+	 * source of StructuredDocument events.
+	 * 
+	 * @param document -
+	 *            the document being changed
+	 */
+	private StructuredDocumentEvent(IStructuredDocument document) {
+		this();
+		if (document == null)
+			throw new IllegalArgumentException("null source"); //$NON-NLS-1$
+		fDocument = document;
+		fOriginalRequester = document;
+	}
+
+	/**
+	 * We assume (and require) that an IStructuredDocument's are always the
+	 * source of StructuredDocument events.
+	 * 
+	 * @param document -
+	 *            the document being changed.
+	 * @param originalRequester -
+	 *            the original requester of the change.
+	 */
+	StructuredDocumentEvent(IStructuredDocument document, Object originalRequester) {
+		this(document);
+		fOriginalRequester = originalRequester;
+	}
+
+	/**
+	 * We assume (and require) that an IStructuredDocument's are always the
+	 * source of StructuredDocument events.
+	 * 
+	 * @param document -
+	 *            the document being changed.
+	 * @param originalRequester -
+	 *            the requester of the change.
+	 * @param changes -
+	 *            the String representing the new text
+	 * @param offset -
+	 *            the offset of the change.
+	 * @param lengthToReplace -
+	 *            the length of text to replace.
+	 */
+	StructuredDocumentEvent(IStructuredDocument document, Object originalRequester, String changes, int offset, int lengthToReplace) {
+		this(document);
+		fOriginalRequester = originalRequester;
+		fText = changes;
+		fOffset = offset;
+		fLength = lengthToReplace;
+	}
+
+	/**
+	 * Provides the text that is being deleted.
+	 * 
+	 * @return the text that is being deleted, or null if none is being
+	 *         deleted.
+	 */
+	public String getDeletedText() {
+		return fDeletedText;
+	}
+
+	/**
+	 * This method returns the object that originally caused the event to
+	 * fire. This is typically not the object that created the event (the
+	 * IStructuredDocument) but instead the object that made a request to the
+	 * IStructuredDocument.
+	 * 
+	 * @return the object that made the request to the document
+	 */
+	public Object getOriginalRequester() {
+		return fOriginalRequester;
+	}
+
+	/**
+	 * This method is equivalent to 'getDocument' except it returns an object
+	 * of the appropriate type (namely, a IStructuredDocument, instead of
+	 * IDocument).
+	 * 
+	 * @return IStructuredDocumnt - the document being changed
+	 */
+	public IStructuredDocument getStructuredDocument() {
+		// a safe case, since constructor can only be called with a
+		// IStructuredDocument
+		return (IStructuredDocument) fDocument;
+	}
+
+	/**
+	 * Not to be called by clients, only parsers and reparsers. (will
+	 * eventually be moved to an SPI package).
+	 * 
+	 * @param newDeletedText -
+	 *            the text that has been deleted.
+	 */
+	public void setDeletedText(String newDeletedText) {
+		fDeletedText = newDeletedText;
+	}
+
+	/**
+	 * for debugging only
+	 * 
+	 * @deprecated - need to fix unit tests which depend on this exact format,
+	 *             then delete this
+	 */
+	public String toString() {
+		// return getClass().getName() + "[source=" + source + "]";
+		return getClass().getName();
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/StructuredDocumentRegionsReplacedEvent.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/StructuredDocumentRegionsReplacedEvent.java
new file mode 100644
index 0000000..8f08b88
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/StructuredDocumentRegionsReplacedEvent.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.events;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList;
+
+/**
+ * This event is used when a IStructuredDocumentRegion is deleted, or replaced
+ * with more than one IStructuredDocumentRegion, or when simply more than one
+ * IStructuredDocumentRegion changes.
+ * 
+ * @plannedfor 1.0
+ */
+public class StructuredDocumentRegionsReplacedEvent extends StructuredDocumentEvent {
+
+	private IStructuredDocumentRegionList fNewStructuredDocumentRegions;
+	private IStructuredDocumentRegionList fOldStructuredDocumentRegions;
+
+	private boolean fIsEntireDocumentReplaced;
+
+	/**
+	 * Creates an instance of StructuredDocumentRegionsReplacedEvent
+	 * 
+	 * @param document -
+	 *            the document being changed.
+	 * @param originalRequester -
+	 *            the requester of the change.
+	 * @param oldStructuredDocumentRegions -
+	 *            the old document regions removed.
+	 * @param newStructuredDocumentRegions -
+	 *            the new document regions added.
+	 * @param changes -
+	 *            a string representing the text change.
+	 * @param offset -
+	 *            the offset of the change.
+	 * @param lengthToReplace -
+	 *            the length of text requested to be replaced.
+	 */
+	public StructuredDocumentRegionsReplacedEvent(IStructuredDocument document, Object originalRequester, IStructuredDocumentRegionList oldStructuredDocumentRegions, IStructuredDocumentRegionList newStructuredDocumentRegions, String changes, int offset, int lengthToReplace) {
+		super(document, originalRequester, changes, offset, lengthToReplace);
+		fOldStructuredDocumentRegions = oldStructuredDocumentRegions;
+		fNewStructuredDocumentRegions = newStructuredDocumentRegions;
+	}
+
+	public StructuredDocumentRegionsReplacedEvent(IStructuredDocument document, Object originalRequester, IStructuredDocumentRegionList oldStructuredDocumentRegions, IStructuredDocumentRegionList newStructuredDocumentRegions, String changes, int offset, int lengthToReplace, boolean entireDocumentReplaced) {
+		this(document, originalRequester, oldStructuredDocumentRegions, newStructuredDocumentRegions, changes, offset, lengthToReplace);
+		fIsEntireDocumentReplaced = entireDocumentReplaced;
+	}
+
+	/**
+	 * Returns the new structured document regions.
+	 * 
+	 * @return the new structured document regions.
+	 */
+	public IStructuredDocumentRegionList getNewStructuredDocumentRegions() {
+		return fNewStructuredDocumentRegions;
+	}
+
+	/**
+	 * Returns the old structured document regions.
+	 * 
+	 * @return the old structured document regions.
+	 */
+	public IStructuredDocumentRegionList getOldStructuredDocumentRegions() {
+		return fOldStructuredDocumentRegions;
+	}
+
+	public boolean isEntireDocumentReplaced() {
+		return fIsEntireDocumentReplaced;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/exceptions/ResourceAlreadyExists.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/exceptions/ResourceAlreadyExists.java
new file mode 100644
index 0000000..79ff0e6
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/exceptions/ResourceAlreadyExists.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.exceptions;
+
+
+
+/**
+ * Indicates that a Resource which a model or document was expected to create
+ * already exists.
+ */
+public class ResourceAlreadyExists extends Exception {
+
+	/**
+	 * Comment for <code>serialVersionUID</code>
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * ResourceAlreadyExists constructor comment.
+	 */
+	public ResourceAlreadyExists() {
+		super();
+	}
+
+	/**
+	 * ResourceAlreadyExists constructor comment.
+	 * 
+	 * @param s
+	 *            java.lang.String
+	 */
+	public ResourceAlreadyExists(String s) {
+		super(s);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/exceptions/ResourceInUse.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/exceptions/ResourceInUse.java
new file mode 100644
index 0000000..5ecbfad
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/exceptions/ResourceInUse.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.exceptions;
+
+
+
+/**
+ * Indicates that a model with a particular ID already exists
+ */
+public class ResourceInUse extends Exception {
+
+	/**
+	 * Comment for <code>serialVersionUID</code>
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * ResourceAlreadyExists constructor comment.
+	 */
+	public ResourceInUse() {
+		super();
+	}
+
+	/**
+	 * ResourceAlreadyExists constructor comment.
+	 * 
+	 * @param s
+	 *            java.lang.String
+	 */
+	public ResourceInUse(String s) {
+		super(s);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/IModelManagerProposed.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/IModelManagerProposed.java
new file mode 100644
index 0000000..ace9420
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/IModelManagerProposed.java
@@ -0,0 +1,338 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.model;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceAlreadyExists;
+import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceInUse;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+/**
+ * Responsible for managing IStructuredModels.
+ * 
+ * This allows clients to share models, so they do not have to be re-created
+ * or passed around from one client to another. Clients should internally
+ * enforce that models are gotten and released from locations close to each
+ * other to prevent model leaks.
+ * 
+ * There are three ways to get a model based on usage and responsibility: for
+ * 'MODIFY', just for 'SHARED', and 'UNSHARED'. Contrary to their names, a
+ * model can technically be modified, and all modifications directly affect
+ * the commonly shared version of the model. It is part of the API contract,
+ * however, that clients who get a model for SHARED do not modify it. The
+ * significance of the 'MODIFY' model is that the client is registering their
+ * interest in saving changes to the model.
+ * 
+ * Clients can reference this interface, but should not implement.
+ * 
+ * @see org.eclipse.wst.sse.core.StructuredModelManager
+ * @plannedfor 1.0
+ */
+public interface IModelManagerProposed {
+
+	/**
+	 * AccessType is used internally as a JRE 1.4 compatible enumerated type.
+	 * Not intended to be referenced by clients.
+	 */
+	static class AccessType {
+		private String fType;
+
+		/**
+		 * default access contructor we use to create our specific constants.
+		 * 
+		 * @param type
+		 */
+		AccessType(String type) {
+			super();
+			fType = type;
+		}
+
+		/**
+		 * For debug purposes only.
+		 */
+		public String toString() {
+			return "Model Access Type: " + fType; //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Constant to provide compile time safe parameter. <code>NOTSHARED</code>signifies
+	 * the client intentially wants a model that is not shared with other
+	 * clients. NOTSHARED models can not be saved.
+	 */
+	final AccessType NOTSHARED = new AccessType("NOTSHARED"); //$NON-NLS-1$
+
+	/**
+	 * Constant to provide compile-time safe parameter. <code>SHARED</code>signifies
+	 * the client is not intending to make changes and does not care whether
+	 * the model accessed is saved.
+	 */
+	final AccessType SHARED = new AccessType("SHARED"); //$NON-NLS-1$
+
+	/**
+	 * Constant to provide compile-time safe parameter. <code>MODIFY</code>signifies
+	 * the client is intending to make changes and is responsible for saving
+	 * changes (or not) if they are the last one holding MODIFY access to the
+	 * model before it's released.
+	 */
+	final AccessType MODIFY = new AccessType("MODIFY"); //$NON-NLS-1$
+
+	/**
+	 * copyModel is similar to a deep clone. The resulting model is shared,
+	 * according to the value of ReadEditType. If a model already is being
+	 * managed for 'newLocation' then a ResourceInUse exception is thrown,
+	 * unless the ReadEditType is NOTSHARED, in which case the resulting model
+	 * can not be saved.
+	 * 
+	 * @param oldLocation
+	 * @param newLocation
+	 * @param type
+	 * @return
+	 * @throws ResourceInUse
+	 * 
+	 * ISSUE: is this important enough to be API, or can clients solve
+	 * themselves
+	 */
+	IStructuredModel copyModel(IPath oldLocation, IPath newLocation, AccessType type) throws ResourceInUse;
+
+	/**
+	 * createNewInstance is similar to clone, except the new instance has no
+	 * text content. Note: this produces an UNSHARED model, for temporary use,
+	 * that has the same characteristics as original model. If a true shared
+	 * model is desired, use "copy".
+	 * 
+	 * ISSUE: still needed?
+	 * 
+	 * @param requester
+	 * @param model
+	 * @return
+	 * @throws IOException
+	 */
+	public IStructuredModel createNewInstance(Object requester, IStructuredModel model) throws IOException;
+
+	/**
+	 * Factory method, since a proper IStructuredDocument must have a proper
+	 * parser assigned. Note: its assume that IPath does not actually exist as
+	 * a resource yet. If it does, ResourceAlreadyExists exception is thrown.
+	 * If the resource does already exist, then createStructuredDocumentFor is
+	 * the right API to use.
+	 * 
+	 * ISSUE: do we want to support this via model manager, or else where?
+	 * ISSUE: do we need two of these? What's legacy use case?
+	 * 
+	 * @param location
+	 * @param progressMonitor
+	 * @return
+	 * @throws ResourceAlreadyExists
+	 * @throws IOException
+	 * @throws CoreException
+	 */
+	IStructuredDocument createNewStructuredDocumentFor(IPath location, IProgressMonitor progressMonitor) throws ResourceAlreadyExists, IOException, CoreException;
+
+	/**
+	 * Factory method, since a proper IStructuredDocument must have a proper
+	 * parser assigned. Note: clients should verify that the resource
+	 * identified by the IPath exists before using this method. If this IFile
+	 * does not exist, then createNewStructuredDocument is the correct API to
+	 * use.
+	 * 
+	 * ISSUE: do we want to support this via model manager, or else where?
+	 * ISSUE: do we need two of these? What's legacy use case?
+	 * 
+	 * @param location
+	 * @param progressMonitor
+	 * @return
+	 * @throws IOException
+	 * @throws CoreException
+	 */
+	IStructuredDocument createStructuredDocumentFor(IPath location, IProgressMonitor progressMonitor) throws IOException, CoreException;
+
+	/**
+	 * Note: callers of this method must still release the model when
+	 * finished. Returns the model for this document if it already exists and
+	 * is being shared. Returns null if this is not the case. The ReadEditType
+	 * must be either MODIFY or SHARED.
+	 * 
+	 * ISSUE: should we accept IDocument on parameter for future evolution,
+	 * and constrain to StructuredDocuments at runtime?
+	 * 
+	 * @param requester
+	 * @param type
+	 * @param document
+	 * @return
+	 */
+	IStructuredModel getExistingModel(Object requester, AccessType type, IDocument document);
+
+	/**
+	 * Callers of this method must still release the model when finished.
+	 * Returns the model for this location if it already exists and is being
+	 * shared. Returns null if this is not the case. The ReadEditType must be
+	 * either MODIFY or SHARED.
+	 * 
+	 * @param requester
+	 * @param type
+	 * @param location
+	 * @return
+	 */
+	public IStructuredModel getExistingModel(Object requester, AccessType type, IPath location);
+
+	/**
+	 * Returns the model that has the specified document as its structured
+	 * document.
+	 * 
+	 * @param requester
+	 * @param type
+	 * @param progressMonitor
+	 * @param document
+	 * @return
+	 */
+	public IStructuredModel getModel(Object requester, AccessType type, IProgressMonitor progressMonitor, IDocument document);
+
+	/**
+	 * Returns the model based on the content at the specified location.
+	 * 
+	 * Note: if the ModelManager does not know how to create a model for 
+	 * such a file for content, null is return.
+	 * ISSUE: should we throw some special, meaningful, checked 
+	 * exception instead?
+	 * 
+	 * @param requester
+	 * @param type
+	 * @param progressMonitor
+	 * @param location
+	 * @return
+	 * @throws IOException
+	 * @throws CoreException
+	 */
+	public IStructuredModel getModel(Object requester, AccessType type, IProgressMonitor progressMonitor, IPath location) throws IOException, CoreException;
+
+	/**
+	 * This method will not create a new model if it already exists ... if
+	 * force is false. The idea is that a client should call this method once
+	 * with force set to false. If the exception is thrown, then prompt client
+	 * if they want to overwrite.
+	 * 
+	 * @param requester
+	 * @param location
+	 * @param force
+	 * @param type
+	 * @param progressMonitor
+	 * @return
+	 * @throws ResourceAlreadyExists
+	 * @throws ResourceInUse
+	 * @throws IOException
+	 * @throws CoreException
+	 */
+	IStructuredModel getNewModel(Object requester, IPath location, boolean force, AccessType type, IProgressMonitor progressMonitor) throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException;
+
+	/**
+	 * This function returns true if there are other references to the
+	 * underlying model.
+	 * 
+	 * @param location
+	 * @return
+	 */
+	boolean isShared(IPath location);
+
+	/**
+	 * This function returns true if there are other references to the
+	 * underlying model, shared in the specified way. The ReadEditType must be
+	 * either MODIFY or SHARED.
+	 * 
+	 * @param location
+	 * @param type
+	 * @return
+	 */
+	boolean isShared(IPath location, AccessType type);
+
+	/**
+	 * This method can be called when the content type of a model changes. Its
+	 * assumed the contentType has already been changed, and this method uses
+	 * the text of the old one, to repopulate the text of the new one.
+	 * 
+	 * @param model
+	 * @return
+	 * @throws IOException
+	 */
+	IStructuredModel reinitialize(IStructuredModel model) throws IOException;
+
+
+	/**
+	 * This is used by clients to signify that they are finished with a model
+	 * and will no longer access it or any of its underlying data (such as its
+	 * structured document). The ReadEditType must match what ever the client
+	 * used in the corresponding 'get' method.
+	 * 
+	 * This method must be called for every 'get'. Clients should use the
+	 * try/finally pattern to ensure the release is called even if there is an
+	 * unexpected exception.
+	 * 
+	 * @param requester
+	 * @param structuredModel
+	 * @param type
+	 */
+	void releaseModel(Object requester, IStructuredModel structuredModel, AccessType type);
+
+	/**
+	 * Writes the underlying document to the IPath.
+	 * 
+	 * ISSUE: we want to just "dump" contents to location, but need to spec.
+	 * all the different cases of shared, etc.
+	 * 
+	 * ?If to same location as 'get', then same instance of model, If to
+	 * different location (esp. if shared) then need to leave old instance of
+	 * model, create new model, and save to new location. ?
+	 * 
+	 * Cases: IPath is null, write to IPath created with IPath specificed and
+	 * equals IPath created with, write to IPath IPath specified and not
+	 * equals IPath created with, dumps to new IPath, no change in current
+	 * model state.
+	 * 
+	 * ISSUE: think through 'normalization' cases
+	 * 
+	 * 
+	 * @param structuredModel
+	 * @param location - already normalized?
+	 * @param progressMonitor
+	 * @throws UnsupportedEncodingException
+	 * @throws IOException
+	 * @throws CoreException
+	 * 
+	 * ISSUE: resource aleady exists? veto override
+	 */
+	void saveModel(IStructuredModel structuredModel, IPath location, IProgressMonitor progressMonitor) throws UnsupportedEncodingException, IOException, CoreException;
+
+	/**
+	 * Writes the underlying document to the IPath if the model is only shared
+	 * for EDIT by one client. This is the recommended way for 'background
+	 * jobs' to save models, in case the model is being shared by an editor,
+	 * or other client that might desire user intervention to save a resource.
+	 * 
+	 * @param structuredModel
+	 * @param location - already normalized?
+	 * @param progressMonitor
+	 * @throws UnsupportedEncodingException
+	 * @throws IOException
+	 * @throws CoreException
+	 * 
+	 * ISSUE: is locaiton needed in this case, or just use the one it was
+	 * created with
+	 */
+	void saveModelIfNotShared(IStructuredModel structuredModel, IPath location, IProgressMonitor progressMonitor) throws UnsupportedEncodingException, IOException, CoreException;
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/IModelStateListenerProposed.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/IModelStateListenerProposed.java
new file mode 100644
index 0000000..484fc70
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/IModelStateListenerProposed.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.model;
+
+
+/**
+ * Interface for those wanting to listen to a model's state changing.
+ * 
+ * @plannedfor 1.0
+ */
+public interface IModelStateListenerProposed {
+
+	/**
+	 * A model is about to be changed. The event object itself signifies which
+	 * model, and any pertinent information.
+	 */
+	void modelAboutToBeChanged(IStructuredModelEvent event);
+
+	/**
+	 * Signals that the changes foretold by modelAboutToBeChanged have been
+	 * made. A typical use might be to refresh, or to resume processing that
+	 * was suspended as a result of modelAboutToBeChanged.
+	 */
+	void modelChanged(IStructuredModelEvent event);
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/INodeAdapterFactoryManager.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/INodeAdapterFactoryManager.java
new file mode 100644
index 0000000..6c2d165
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/INodeAdapterFactoryManager.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 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.wst.sse.core.internal.provisional.model;
+
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
+/**
+ * Provides a means for clients to register IAdapterFactories for use
+ * by infrastructure when StructuredModels are created. 
+ */
+public interface INodeAdapterFactoryManager {
+
+	/**
+	 * 
+	 * @param factory
+	 * @param contentType
+	 */
+	void addAdapterFactory(INodeAdapterFactory factory, IContentType contentType);
+
+	void removeAdapterFactory(INodeAdapterFactory factory, IContentType contentType);
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/IStructuredModelEvent.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/IStructuredModelEvent.java
new file mode 100644
index 0000000..73bc3be
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/IStructuredModelEvent.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * 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.wst.sse.core.internal.provisional.model;
+
+public interface IStructuredModelEvent {
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/IStructuredModelProposed.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/IStructuredModelProposed.java
new file mode 100644
index 0000000..7d984da
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/model/IStructuredModelProposed.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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.wst.sse.core.internal.provisional.model;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.wst.sse.core.internal.model.FactoryRegistry;
+import org.eclipse.wst.sse.core.internal.provisional.IModelStateListener;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+
+/**
+ * IStructuredModel's are mainly interesting by their extensions and
+ * implementers. The main purposed of this abstraction it to provide a common
+ * way to manage models that have an associated structured documnet.
+ * 
+ * @plannedfor 1.0
+ * 
+ */
+public interface IStructuredModelProposed extends IAdaptable {
+
+
+	/**
+	 * This API allows clients to declare that they are about to make a
+	 * "large" change to the model. This change might be in terms of content
+	 * or it might be in terms of the model id or base location.
+	 * 
+	 * Note that in the case of embedded calls, notification to listeners is
+	 * sent only once.
+	 * 
+	 * Note that the client who is making these changes has the responsibility
+	 * to restore the model's state once finished with the changes. See
+	 * getMemento and restoreState.
+	 * 
+	 * The method isModelStateChanging can be used by a client to determine if
+	 * the model is already in a change sequence.
+	 * 
+	 * This method is a matched pair to changedModel, and must be called
+	 * before changedModel. A client should never call changedModel without
+	 * calling aboutToChangeModel first nor call aboutToChangeModel without
+	 * calling changedModel later from the same Thread.
+	 */
+	void aboutToChangeModel();
+
+	void addModelStateListener(IModelStateListener listener);
+
+	/**
+	 * This API allows a client controlled way of notifying all ModelEvent
+	 * listners that the model has been changed. This method is a matched pair
+	 * to aboutToChangeModel, and must be called after aboutToChangeModel ...
+	 * or some listeners could be left waiting indefinitely for the changed
+	 * event. So, its suggested that changedModel always be in a finally
+	 * clause. Likewise, a client should never call changedModel without
+	 * calling aboutToChangeModel first.
+	 * 
+	 * In the case of embedded calls, the notification is just sent once.
+	 * 
+	 */
+	void changedModel();
+
+	/**
+	 * This is a client-defined value for what that client (and/or loader)
+	 * considers the "base" of the structured model. Frequently the location
+	 * is either a workspace root-relative path of a workspace resource or an
+	 * absolute path in the local file system.
+	 */
+	IPath getLocation();
+
+	/**
+	 * @return The associated content type identifier (String) for this model.
+	 */
+	IContentType getContentType() throws CoreException;
+
+	/**
+	 * 
+	 * @return The model's FactoryRegistry. A model is not valid without one.
+	 */
+	FactoryRegistry getFactoryRegistry();
+
+	/**
+	 * Return the index region at offset. Returns null if there is no
+	 * IndexedRegion that contains offset.
+	 */
+	IndexedRegion getIndexedRegion(int offset);
+
+	/**
+	 * ISSUE: do we want to provide this? How to ensure job/thread safety
+	 * 
+	 * @return
+	 */
+	IndexedRegion[] getIndexedRegions();
+
+	/**
+	 * Rreturns the IStructuredDocument that underlies this model
+	 * 
+	 * @return
+	 */
+	IStructuredDocument getStructuredDocument();
+
+	/**
+	 * 
+	 */
+	boolean isDirty();
+
+	/**
+	 * This method can be called to determine if the model is within a
+	 * "aboutToChange" and "changed" sequence.
+	 */
+	public boolean isModelStateChanging();
+
+	/**
+	 * 
+	 */
+	boolean isNew();
+
+	boolean isReinitializationNeeded();
+
+	/**
+	 * This is a combination of if the model is dirty and if the model is
+	 * shared for write access. The last writer as the responsibility to be
+	 * sure the user is prompted to save.
+	 */
+	public boolean isSaveNeeded();
+
+	/**
+	 * newInstance is similar to clone, except that the newInstance contains
+	 * no content. Its purpose is so clients can get a temporary, unmanaged,
+	 * model of the same "type" as the original. Note: the client may still
+	 * need to do some intialization of the model returned by newInstance,
+	 * depending on desired use. For example, the only factories in the
+	 * newInstance are those that would be normally be created for a model of
+	 * the given contentType. Others are not copied automatically, and if
+	 * desired, should be added by client.
+	 */
+	IStructuredModelProposed newInstance() throws IOException;
+
+	void removeModelStateListener(IModelStateListener listener);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredDocument.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredDocument.java
new file mode 100644
index 0000000..97d4ef6
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredDocument.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.text;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.text.IDocumentExtension;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument;
+import org.eclipse.wst.sse.core.internal.provisional.events.IModelAboutToBeChangedListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager;
+
+
+/**
+ * A IStructuredDocument is a collection of StructuredDocumentRegions. It's
+ * often called "flat" because its contents by design do not contain much
+ * structural information beyond containment. Clients should not implement.
+ */
+public interface IStructuredDocument extends IEncodedDocument, IDocumentExtension, IAdaptable {
+
+	void addDocumentAboutToChangeListener(IModelAboutToBeChangedListener listener);
+
+	/**
+	 * The StructuredDocumentListeners and ModelChangedListeners are very
+	 * similar. They both receive identical events. The difference is the
+	 * timing. The "pure" StructuredDocumentListeners are notified after the
+	 * structuredDocument has been changed, but before other, related models
+	 * may have been changed such as the Structural Model. The Structural
+	 * model is in fact itself a "pure" StructuredDocumentListner. The
+	 * ModelChangedListeners can rest assured that all models and data have
+	 * been updated from the change by the tiem they are notified. This is
+	 * especially important for the text widget, for example, which may rely
+	 * on both structuredDocument and structural model information.
+	 */
+	void addDocumentChangedListener(IStructuredDocumentListener listener);
+
+	/**
+	 * The StructuredDocumentListeners and ModelChangedListeners are very
+	 * similar. They both receive identical events. The difference is the
+	 * timing. The "pure" StructuredDocumentListeners are notified after the
+	 * structuredDocument has been changed, but before other, related models
+	 * may have been changed such as the Structural Model. The Structural
+	 * model is in fact itself a "pure" StructuredDocumentListner. The
+	 * ModelChangedListeners can rest assured that all models and data have
+	 * been updated from the change by the tiem they are notified. This is
+	 * especially important for the text widget, for example, which may rely
+	 * on both structuredDocument and structural model information.
+	 */
+	void addDocumentChangingListener(IStructuredDocumentListener listener);
+
+	/**
+	 * this API ensures that any portion of the document within startOff to
+	 * length is not readonly (that is, that its editable). Note that if the
+	 * range overlaps with other readonly regions, those other readonly
+	 * regions will be adjusted.
+	 * 
+	 * @param startOffset
+	 * @param length
+	 */
+	void clearReadOnly(int startOffset, int length);
+
+	/**
+	 * returns true if any portion of startOffset to length is readonly
+	 * 
+	 * @param startOffset
+	 * @param length
+	 * @return
+	 */
+	boolean containsReadOnly(int startOffset, int length);
+
+	/**
+	 * This method is to remember info about the encoding When the resource
+	 * was last loaded or saved. Note: it is not kept "current", that is, can
+	 * not be depended on blindly to reflect what encoding to use. For that,
+	 * must go through the normal rules expressed in Loaders and Dumpers.
+	 */
+
+	EncodingMemento getEncodingMemento();
+
+	org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion getFirstStructuredDocumentRegion();
+
+	org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion getLastStructuredDocumentRegion();
+
+	/**
+	 * This can be considered the preferred delimiter.
+	 */
+	public String getLineDelimiter();
+
+	int getLineOfOffset(int offset); // throws SourceEditingException;
+
+	/**
+	 * The parser is now required on constructor, so there are occasions it
+	 * needs to be retrieved, such as to be initialized by EmbeddedContentType
+	 */
+	RegionParser getParser();
+
+	/**
+	 * @deprecated use getStructuredDocumentRegions()
+	 * @return
+	 */
+	IStructuredDocumentRegionList getRegionList();
+
+	/**
+	 * Returns the <code>IStructuredDocumentRegion</code> at the given character offset.
+	 * @param offset
+	 * @return the <code>IStructuredDocumentRegion</code> at the given character offset.
+	 */
+	IStructuredDocumentRegion getRegionAtCharacterOffset(int offset);
+	
+	/**
+	 * Returns <code>IStructuredDocumentRegion</code>s in the specified range.
+	 * @param offset
+	 * @param length
+	 * @return <code>IStructuredDocumentRegion</code>s in the specified range.
+	 */
+	IStructuredDocumentRegion[] getStructuredDocumentRegions(int offset, int length);
+	
+	/**
+	 * Returns all <code>IStructuredDocumentRegion</code>s in the document.
+	 * @return all <code>IStructuredDocumentRegion</code>s in the document.
+	 */
+	IStructuredDocumentRegion[] getStructuredDocumentRegions();
+	
+	/**
+	 * Note: this method was made public, and part of the interface, for
+	 * easier testing. Clients normally never manipulate the reparser directly
+	 * (nor should they need to).
+	 */
+	IStructuredTextReParser getReParser();
+
+	String getText();
+
+	IStructuredTextUndoManager getUndoManager();
+
+	/**
+	 * causes that portion of the document from startOffset to length to be
+	 * marked as readonly. Note that if this range overlaps with some other
+	 * region with is readonly, the regions are effectivly combined.
+	 * 
+	 * @param startOffset
+	 * @param length
+	 */
+	void makeReadOnly(int startOffset, int length);
+
+	/**
+	 * newInstance is similar to clone, except it contains no data. One
+	 * important thing to duplicate is the parser, with the parser correctly
+	 * "cloned", including its tokeninzer, block tags, etc.
+	 * 
+	 * NOTE: even after obtaining a 'newInstance' the client may have to do
+	 * some initialization, for example, it may need to add its own model
+	 * listeners. Or, as another example, if the IStructuredDocument has a
+	 * parser of type StructuredDocumentRegionParser, then the client may need
+	 * to add its own StructuredDocumentRegionHandler to that parser, if it is
+	 * in fact needed.
+	 */
+	IStructuredDocument newInstance();
+
+	void removeDocumentAboutToChangeListener(IModelAboutToBeChangedListener listener);
+
+	void removeDocumentChangedListener(IStructuredDocumentListener listener);
+
+	void removeDocumentChangingListener(IStructuredDocumentListener listener);
+
+	/**
+	 * One of the APIs to manipulate the IStructuredDocument.
+	 * 
+	 * replaceText replaces the text from oldStart to oldEnd with the new text
+	 * found in the requestedChange string. If oldStart and oldEnd are equal,
+	 * it is an insertion request. If requestedChange is null (or empty) it is
+	 * a delete request. Otherwise it is a replace request.
+	 */
+	StructuredDocumentEvent replaceText(Object source, int oldStart, int replacementLength, String requestedChange);
+
+	/**
+	 * Note, same as replaceText API, but will allow readonly areas to be
+	 * replaced. This should seldom be called with a value of "true" for
+	 * ignoreReadOnlySetting. One case where its ok is with undo operations
+	 * (since, presumably, if user just did something that happended to
+	 * involve some inserting readonly text, they should normally be allowed
+	 * to still undo that operation. Otherwise, I can't think of a single
+	 * example, unless its to give the user a choice, e.g. "you are about to
+	 * overwrite read only portions, do you want to continue".
+	 */
+	StructuredDocumentEvent replaceText(Object source, int oldStart, int replacementLength, String requestedChange, boolean ignoreReadOnlySetting);
+
+	/**
+	 * This method is to remember info about the encoding When the resource
+	 * was last loaded or saved. Note: it is not kept "current", that is, can
+	 * not be depended on blindly to reflect what encoding to use. For that,
+	 * must go through the normal rules expressed in Loaders and Dumpers.
+	 */
+	void setEncodingMemento(EncodingMemento encodingMemento);
+
+	public void setLineDelimiter(String delimiter);
+
+	/**
+	 * One of the APIs to manipulate the IStructuredDocument in terms of Text.
+	 * 
+	 * The setText method replaces all text in the model.
+	 */
+	StructuredDocumentEvent setText(Object requester, String allText);
+
+	void setUndoManager(IStructuredTextUndoManager undoManager);
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredDocumentRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredDocumentRegion.java
new file mode 100644
index 0000000..8b03b2a
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredDocumentRegion.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.text;
+
+/**
+ * A ITextRegionCollection is a collection of ITextRegions. It is a structural
+ * unit, but a minimal one. For example, in might consist of a "start tag" but
+ * not a whole XML element.
+ */
+public interface IStructuredDocumentRegion extends ITextRegionCollection {
+
+	/**
+	 * Adds a text region to the end of the collection of regions contained by
+	 * this region. It is the parsers responsibility to make sure its a
+	 * correct region (that is, its start offset is one greater than previous
+	 * regions end offset)
+	 * 
+	 * For use by parsers and reparsers only.
+	 */
+	void addRegion(ITextRegion aRegion);
+
+	/**
+	 * Returns the structured document region that follows this one or null if
+	 * at end of document.
+	 * 
+	 * @return the structured document region that follows this one.
+	 * 
+	 * ISSUE: for thread safety, this should be more restrictive.
+	 */
+	IStructuredDocumentRegion getNext();
+
+	/**
+	 * Returns this regions parent document.
+	 * 
+	 * @return this regions parent document.
+	 */
+	IStructuredDocument getParentDocument();
+
+	/**
+	 * Returns the structured document region that preceeds this one or null
+	 * if at beginning of document.
+	 * 
+	 * @return the structured document region that follows this one.
+	 * 
+	 * ISSUE: for thread safety, this should be more restrictive.
+	 */
+	IStructuredDocumentRegion getPrevious();
+
+	/**
+	 * Returns true if this document has been deleted, and is no longer part
+	 * of the actual structured document. This field can be used in
+	 * multi-threaded operations, which may retrieve a long list of regions
+	 * and be iterating through them at the same time the document is
+	 * modified, and regions deleted.
+	 * 
+	 * @return true if this region is no longer part of document.
+	 */
+	boolean isDeleted();
+
+	/**
+	 * Returns true if this structured document region was ended "naturally"
+	 * by syntactic rules, or if simply assumed to end so another could be
+	 * started.
+	 * 
+	 * @return true if region has syntactic end.
+	 */
+	boolean isEnded();
+
+	/**
+	 * Tests is region is equal to this one, ignoring position offsets of
+	 * shift.
+	 * 
+	 * For use by parsers and reparsers only.
+	 * 
+	 * @param region
+	 * @param shift
+	 * @return
+	 */
+	boolean sameAs(IStructuredDocumentRegion region, int shift);
+
+	/**
+	 * Tests if <code>oldRegion</code> is same as <code>newRegion</code>,
+	 * ignoring position offsets of <code>shift</code>.
+	 * 
+	 * ISSUE: which document region are old and new in?
+	 * 
+	 * For use by parsers and reparsers only.
+	 * 
+	 * @param oldRegion
+	 * @param documentRegion
+	 * @param newRegion
+	 * @param shift
+	 * @return
+	 */
+	boolean sameAs(ITextRegion oldRegion, IStructuredDocumentRegion documentRegion, ITextRegion newRegion, int shift);
+
+	/**
+	 * Set to true if/when this region is removed from a document, during the
+	 * process of re-parsing.
+	 * 
+	 * For use by parsers and reparsers only.
+	 * 
+	 * @param deleted
+	 */
+	void setDeleted(boolean deleted);
+
+	/**
+	 * Set to true by parser/reparser if region deemed to end syntactically.
+	 * 
+	 * For use by parsers and reparsers only.
+	 * 
+	 * @param hasEnd
+	 */
+	void setEnded(boolean hasEnd);
+
+	/**
+	 * Sets length of region.
+	 * 
+	 * For use by parsers and reparsers only.
+	 */
+	void setLength(int newLength);
+
+	/**
+	 * Assigns pointer to next region, or null if last region.
+	 * 
+	 * For use by parsers and reparsers only.
+	 */
+	void setNext(IStructuredDocumentRegion newNext);
+
+	/**
+	 * Assigns parent documnet.
+	 * 
+	 * For use by parsers and reparsers only.
+	 */
+	void setParentDocument(IStructuredDocument document);
+
+	/**
+	 * Assigns pointer to previous region, or null if first region.
+	 * 
+	 * For use by parsers and reparsers only.
+	 */
+	void setPrevious(IStructuredDocumentRegion newPrevious);
+
+	/**
+	 * Sets start offset of region, relative to beginning of document.
+	 * 
+	 * For use by parsers and reparsers only.
+	 */
+	void setStart(int newStart);
+
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredDocumentRegionList.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredDocumentRegionList.java
new file mode 100644
index 0000000..734431e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredDocumentRegionList.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.text;
+
+import java.util.Enumeration;
+
+/**
+ * This is a class used to provide a list of StructuredDocumentRegions, so the
+ * implementation of how the list is formed can be hidden (encapsulated by
+ * this class).
+ * 
+ * ISSUE: should extend ITextRegionList instead?
+ * 
+ * @plannedfor 1.0
+ * 
+ */
+public interface IStructuredDocumentRegionList {
+
+	/**
+	 * Returns enumeration.
+	 * 
+	 * @return enumeration.
+	 */
+	Enumeration elements();
+
+	/**
+	 * Returns size of list.
+	 * 
+	 * @return size of list.
+	 */
+	int getLength();
+
+	/**
+	 * Returns the structured document region at index i.
+	 * 
+	 * @param i
+	 *            index of region to return
+	 * @return the region at specified offset.
+	 */
+	IStructuredDocumentRegion item(int i);
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredPartitionTypes.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredPartitionTypes.java
new file mode 100644
index 0000000..17c2019
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredPartitionTypes.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.text;
+
+/**
+ * This interface is not intended to be implemented.
+ * It defines the partitioning for StructuredDocuments.
+ * Clients should reference the partition type Strings defined here directly.
+ * 
+ * @deprecated use org.eclipse.wst.sse.core.internal.provisional.text.IStructuredPartitions
+ */
+public interface IStructuredPartitionTypes {
+
+	String DEFAULT_PARTITION = "org.eclipse.wst.sse.ST_DEFAULT"; //$NON-NLS-1$
+	String UNKNOWN_PARTITION = "org.eclipse.wst.sse.UNKNOWN_PARTITION_TYPE"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredPartitioning.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredPartitioning.java
new file mode 100644
index 0000000..f7e940c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredPartitioning.java
@@ -0,0 +1,12 @@
+package org.eclipse.wst.sse.core.internal.provisional.text;
+
+/**
+ * Identifies the way that Documents are partitioned.
+ * 
+ * @plannedfor 1.0
+ */
+public interface IStructuredPartitioning {
+	
+	/** String to identify default partitioning*/
+	String DEFAULT_STRUCTURED_PARTITIONING = "org.eclipse.wst.sse.core.default_structured_text_partitioning"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredTextPartitioner.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredTextPartitioner.java
new file mode 100644
index 0000000..9e53f8f
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredTextPartitioner.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.text;
+
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.wst.sse.core.internal.text.rules.IStructuredTypedRegion;
+
+
+/**
+ * A partitioner interface required for handling the embedded content type 
+ * properly. 
+ * 
+ * ISSUE: need to investigate necessity of these methods
+ * 
+ * @plannedfor 1.0
+ */
+
+public interface IStructuredTextPartitioner extends IDocumentPartitioner {
+
+	/**
+	 * Used by JSP partitioner to ensure that the partitioner of the
+	 * embedded content type gets to create the partition in case the specific
+	 * classes are important.
+	 * 
+	 * ISSUE: investigate if we really need this...
+	 */
+	IStructuredTypedRegion createPartition(int offset, int length, String partitionType);
+
+	/**
+	 * Returns the Default partition type for this partitioner.
+	 * <p>
+	 * eg:
+	 * <br><code>org.eclipse.wst.xml.core.text.IXMLPartitions.XML_DEFAULT</code>
+	 * <br><code>org.eclipse.wst.html.core.text.IHTMLPartitions.HTML_DEFAULT</code>
+	 * <br><code>org.eclipse.wst.jsp.core.text.IJSPPartitions.JSP_DEFAULT</code>
+	 * </p>
+	 * @see org.eclipse.wst.sse.core.text.IStructuredPartitions
+	 * @see org.eclipse.wst.xml.core.text.IXMLPartitions
+	 * @see org.eclipse.wst.html.core.text.IHTMLPartitions
+	 * @see org.eclipse.wst.jsp.core.text.IJSPPartitions
+	 * 
+	 * @return the Default partition type for this partitioner.
+	 */
+	String getDefaultPartitionType();
+
+	/**
+	 * Returns the particular partition type for the given region/offset.
+	 * <p>
+	 * eg:
+	 * <br><code>org.eclipse.wst.xml.core.text.IXMLPartitions.XML_DEFAULT</code>
+	 * <br><code>org.eclipse.wst.html.core.text.IHTMLPartitions.HTML_DEFAULT</code>
+	 * <br><code>org.eclipse.wst.jsp.core.text.IJSPPartitions.JSP_DEFAULT</code>
+	 * </p>
+	 * 
+	 * @param region of the IStructuredDocument
+	 * @param offset in the IStructuredDoucment
+	 * @return the particular partition type for the given region/offset.
+	 */
+	String getPartitionType(ITextRegion region, int offset);
+
+	/**
+	 * Returns the partition type String of the IStructuredDocumentRegion 
+	 * between the 2 region parameters.
+	 * Useful for finding the partition type of a 0 length region.
+	 * eg.
+	 * <pre>
+	 * 	<script type="text/javascript">|</script>
+	 * </pre>
+	 * @param previousNode
+	 * @param nextNode
+	 * @return the partition type of the node between previousNode and nextNode
+	 * @deprecated move to IDocumentPartitionerExtension2 ->
+	 *  String getContentType(int offset, boolean preferOpenPartitions);
+	 */
+	String getPartitionTypeBetween(IStructuredDocumentRegion previousNode, IStructuredDocumentRegion nextNode);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredTextReParser.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredTextReParser.java
new file mode 100644
index 0000000..5acdfa1
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/IStructuredTextReParser.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.text;
+
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+
+/**
+ * IStructuredTextReParser describes the characteristics and responsibilities
+ * for reparsing a structured document.
+ * 
+ * @plannedfor 1.0
+ */
+public interface IStructuredTextReParser {
+
+	/**
+	 * Begins the process of reparsing, by providing the information needed
+	 * for the reparse. The reparse is actually performed when the reparse
+	 * method is called. Will through an IllegalStateException if document as
+	 * not be set.
+	 * 
+	 * @param requester
+	 * @param start
+	 * @param lengthToReplace
+	 * @param changes
+	 */
+	void initialize(Object requester, int start, int lengthToReplace, String changes);
+
+	/**
+	 * This method is provided to enable multiple threads to reparse a
+	 * document. This is needed since the intialize method sets state
+	 * variables that must be "in sync" with the structuredDocument.
+	 */
+	public boolean isParsing();
+
+	/**
+	 * Returns a new instance of this reparser, used when cloning documents.
+	 * 
+	 * @return a new instance of this reparser.
+	 */
+	public IStructuredTextReParser newInstance();
+
+	/**
+	 * An entry point for reparsing. It needs to calculates the dirty start
+	 * and dirty end in terms of structured document regions based on the
+	 * start point and length of the changes, which are provided by the
+	 * initialize method. Will through an IllegalStateException if document as
+	 * not be set.
+	 * 
+	 */
+	public StructuredDocumentEvent reparse();
+
+
+
+	/**
+	 * The reparser is initialized with its document, either in or shortly
+	 * after its constructed is called.
+	 * 
+	 * @param structuredDocument
+	 */
+	public void setStructuredDocument(IStructuredDocument newStructuredDocument);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/ITextRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/ITextRegion.java
new file mode 100644
index 0000000..b1281ab
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/ITextRegion.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.text;
+
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+
+/**
+ * A simple description of a bit of text (technically, a bit of a text buffer)
+ * that has a "type" associated with it. For example, for the XML text
+ * "&LT;IMG&GT;", the ' <' might form a region of type "open bracket" where as
+ * the text "IMG" might form a region of type "tag name".
+ * 
+ * Note that there are three positions associated with a region, the start,
+ * the end, and the end of the text. The end of the region should always be
+ * greater than or equal to the end of the text, because the end of the text
+ * simply includes any white space that might follow the non-whitespace
+ * portion of the region. This whitespace is assumed to be ignorable except
+ * for reasons of maintaining it in the original document for formatting,
+ * appearance, etc.
+ * 
+ * Follows the Prime Directives:
+ * 
+ * getEnd() == getStart() + getLength()
+ * 
+ * getTextEnd() == getStart() + getTextLength();
+ * 
+ * Event though 'end' and 'length' are redundant (given start), both methods
+ * are provided, since some parsers/implementations favor one or the other for
+ * efficiency.
+ * 
+ * @plannedfor 1.0
+ */
+public interface ITextRegion {
+
+	/**
+	 * Changes length of region. May be less than, equal to, or greater than
+	 * zero. It may not, however, cause the length of the region to be less
+	 * than or equal to zero, or an illegal argument acception may be thrown
+	 * at runtime.
+	 * 
+	 * For use by parsers and reparsers only.
+	 */
+	void adjustLength(int i);
+
+	/**
+	 * Changes start offset of region. May be less than, equal to, or greater
+	 * than zero. It may not, however, cause the offset of the region to be
+	 * less than zero, or an illegal argument acception may be thrown at
+	 * runtime.
+	 * 
+	 * For use by parsers and reparsers only.
+	 */
+	void adjustStart(int i);
+
+	/**
+	 * Changes text length of region.
+	 * 
+	 * May be less than, equal to, or greater than zero. It may not, however,
+	 * cause the text length of the region to be greater than the length of a
+	 * region, or an illegal argument acception may be thrown at runtime.
+	 * 
+	 * For use by parsers and reparsers only.
+	 */
+	void adjustTextLength(int i);
+
+	/**
+	 * Makes this regions start, length, and text length equal to the
+	 * paremter's start, length, and text length.
+	 * 
+	 * @param region
+	 */
+	void equatePositions(ITextRegion region);
+
+	/**
+	 * Returns the end offset of this region. Whether is relative to the
+	 * document, or another region depends on the subtype.
+	 * 
+	 * Follows the Prime Directive: getEnd() == getStart() + getLength()
+	 * 
+	 * @return the end offset of this region.
+	 */
+	int getEnd();
+
+	/**
+	 * Returns the length of the region.
+	 * 
+	 * Follows the Prime Directive: getEnd() == getStart() + getLength()
+	 * 
+	 * @return the length of the region.
+	 */
+	int getLength();
+
+	/**
+	 * Returns the start of the region. Whether is relative to the document,
+	 * or another region depends on the subtype.
+	 * 
+	 * Follows the Prime Directive: getEnd() == getStart() + getLength()
+	 * 
+	 * @return the start of the region.
+	 */
+	int getStart();
+
+	/**
+	 * Returns the end offset of the text of this region.
+	 * 
+	 * In some implementations, the "end" of the region (accessible via
+	 * getEnd()) also contains any and all white space that may or may not be
+	 * present after the "token" (read: relevant) part of the region. This
+	 * method, getTextEnd(), is specific for the "token" part of the region,
+	 * without the whitespace.
+	 * 
+	 * @return the end offset of the text of this region.
+	 */
+	int getTextEnd();
+
+	/**
+	 * Returns the length of the text of this region.
+	 * 
+	 * The text length is equal to length if there is no white space at the
+	 * end of a region. Otherwise it is smaller than length.
+	 * 
+	 * @return the length of the text of this region.
+	 */
+	int getTextLength();
+
+	/**
+	 * Returns the type of this region.
+	 * 
+	 * @see regiontypes, structureddocumentregiontypes
+	 * @return the type of this region.
+	 */
+	String getType();
+
+	/**
+	 * Allows the region itself to participate in reparsing process.
+	 * 
+	 * The region itself can decide if it can determine the appropriate event
+	 * to return, based on the requested change. If it can not, this method
+	 * must return null, so a "higher level" reparsing process will be given
+	 * the oppurtunity to decide. If it returns an Event, that's it, not other
+	 * reparsing process will get an oppurtunity to reparse.
+	 * 
+	 * For use by parsers and reparsers only.
+	 * 
+	 */
+	StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion parent, String changes, int requestStart, int lengthToReplace);
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/ITextRegionCollection.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/ITextRegionCollection.java
new file mode 100644
index 0000000..08890ae
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/ITextRegionCollection.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.text;
+
+/**
+ * ITextRegionCollection, as its name implies, is a collection of
+ * ITextRegions.
+ * 
+ * @plannedfor 1.0
+ */
+public interface ITextRegionCollection extends ITextRegion {
+
+	/**
+	 * Used to determine if a region contains a particular offset, where
+	 * offset is relative to the beginning of a document.
+	 * 
+	 * @param offset
+	 * @return true if offset is greater than or equal to regions start and
+	 *         less than its end offset.
+	 */
+	boolean containsOffset(int offset);
+
+	/**
+	 * Used to determine if a region contains a particular offset.
+	 * 
+	 * ISSUE: I need to figure out what this is really for! (that is, how to
+	 * describe it, or if still needed).
+	 * 
+	 * @param offset
+	 * @return true if offset is greater than or equal to regions start and
+	 *         less than its end offset.
+	 */
+	boolean containsOffset(ITextRegion region, int offset);
+
+	/**
+	 * Returns the end offset of this region, relative to beginning of
+	 * document.
+	 * 
+	 * For some subtypes, but not all, it is equivilent to getEnd().
+	 * 
+	 * @return the end offset of this region.
+	 */
+	int getEndOffset();
+
+	/**
+	 * Returns the end offset, relative to the beginning of the document of
+	 * the contained region.
+	 * 
+	 * @param containedRegion
+	 * @return the end offset of the contained region.
+	 */
+	int getEndOffset(ITextRegion containedRegion);
+
+	/**
+	 * Returns the first region of those contained by this region collection.
+	 * 
+	 * @return the first region.
+	 */
+	ITextRegion getFirstRegion();
+
+	/**
+	 * Returns the full text of this region, including whitespace.
+	 * 
+	 * @return the full text of this region, including whitespace.
+	 */
+	String getFullText();
+
+	/**
+	 * Returns the full text of the contained region, including whitespace.
+	 * 
+	 * @return the full text of the contained region, including whitespace.
+	 */
+	String getFullText(ITextRegion containedRegion);
+
+	/**
+	 * Returns the last region of those contained by this region collection.
+	 * 
+	 * @return the last region.
+	 */
+	ITextRegion getLastRegion();
+
+	/**
+	 * Returns the number of regions contained by this region.
+	 * 
+	 * @return the number of regions contained by this region.
+	 */
+	int getNumberOfRegions();
+
+	/**
+	 * Returns the region that contains offset. In the case of "nested"
+	 * regions, returns the top most region.
+	 * 
+	 * @param offset
+	 *            relative to beginning of document.
+	 * @return the region that contains offset. In the case of "nested"
+	 *         regions, returns the top most region.
+	 */
+	ITextRegion getRegionAtCharacterOffset(int offset);
+
+	/**
+	 * Returns the regions contained by this region.
+	 * 
+	 * Note: no assumptions should be made about the object identity of the
+	 * regions returned. Put another way, due to memory use optimizations,
+	 * even if the underlying text has not changed, the regions may or may not
+	 * be the same ones returned from one call to the next.
+	 * 
+	 * @return the regions contained by this region.
+	 */
+	ITextRegionList getRegions();
+
+	/**
+	 * Returns the start offset of this region, relative to the beginning of
+	 * the document.
+	 * 
+	 * @return the start offset of this region
+	 */
+	int getStartOffset();
+
+	/**
+	 * Returns the start offset of the contained region, relative to the
+	 * beginning of the document.
+	 * 
+	 * @return the start offset of the contained region
+	 */
+	int getStartOffset(ITextRegion containedRegion);
+
+	/**
+	 * Returns the text of this region, not including white space.
+	 * 
+	 * @return the text of this region, not including white space.
+	 */
+	String getText();
+
+	/**
+	 * Returns the text of the contained region, not including white space.
+	 * 
+	 * @return the text of the contained region, not including white space.
+	 */
+	String getText(ITextRegion containedRegion);
+
+	/**
+	 * Returns the end offset of the text of this region, not including white
+	 * space.
+	 * 
+	 * @return the end offset of the text of this region, not including white
+	 *         space.
+	 */
+	int getTextEndOffset();
+
+	/**
+	 * Returns the end offset of the text of the contained region, not
+	 * including white space.
+	 * 
+	 * @return the end offset of the text of the contained region, not
+	 *         including white space.
+	 */
+	int getTextEndOffset(ITextRegion containedRegion);
+
+	/**
+	 * Assigns the collection contained in this region.
+	 * 
+	 * For use by parsers and reparsers only.
+	 * 
+	 * @param containedRegions
+	 */
+	void setRegions(ITextRegionList containedRegions);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/ITextRegionContainer.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/ITextRegionContainer.java
new file mode 100644
index 0000000..654ca81
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/ITextRegionContainer.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.text;
+
+/**
+ * ITextRegionContainer contains other regions, like a ITextRegionCollection
+ * but is itself a region in an ITextRegionCollection, so its "parent" region
+ * is maintained.
+ * 
+ * @plannedfor 1.0
+ */
+public interface ITextRegionContainer extends ITextRegionCollection {
+
+	/**
+	 * Returns the parent region.
+	 * 
+	 * @return the parent region.
+	 */
+	ITextRegionCollection getParent();
+
+	/**
+	 * Sets the parent region.
+	 * 
+	 * For use by parsers and reparsers only.
+	 * 
+	 * @param parent
+	 *            the ITextRegionCollection this region is contained in.
+	 */
+	void setParent(ITextRegionCollection parent);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/ITextRegionList.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/ITextRegionList.java
new file mode 100644
index 0000000..594d3e8
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/text/ITextRegionList.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.provisional.text;
+
+import java.util.Iterator;
+
+/**
+ * ITextRegionList is to provide a list of regions. It can be used so clients
+ * do not need to be aware of underlying implementation.
+ */
+public interface ITextRegionList {
+
+	/**
+	 * Adds region to the list.
+	 * 
+	 * For use by parsers and reparsers only, while list is being created.
+	 * 
+	 * @param region
+	 * @return
+	 */
+	public boolean add(ITextRegion region);
+
+	/**
+	 * Adds new regions to the list.
+	 * 
+	 * For use by parsers and reparsers only, while list is being created.
+	 * 
+	 * @param insertPos
+	 * @param newRegions
+	 * @return whether the contents of this list were modified
+	 */
+	public boolean addAll(int insertPos, ITextRegionList newRegions);
+
+	/**
+	 * Removes all regions from the list.
+	 * 
+	 * For use by parsers and reparsers only, while list is being created.
+	 * 
+	 */
+	public void clear();
+
+
+	/**
+	 * Returns the region at <code>index</code>, where 0 is first one in
+	 * the list. Throws an <code>ArrayIndexOutOfBoundsException</code> if
+	 * list is empty, or if index is out of range.
+	 * 
+	 * @param index
+	 * @return
+	 */
+	public ITextRegion get(int index);
+
+	/**
+	 * Returns the index of <code>region</code> or -1 if <code>region</code>
+	 * is not in the list.
+	 * 
+	 * @param region
+	 * @return
+	 */
+	public int indexOf(ITextRegion region);
+
+	/**
+	 * Returns true if list has no regions.
+	 * 
+	 * @return true if list has no regions.
+	 */
+	public boolean isEmpty();
+
+
+	/**
+	 * Returns an iterator for this list.
+	 * 
+	 * @return an iterator for this list.
+	 */
+	public Iterator iterator();
+
+	/**
+	 * Removes the region at index.
+	 * 
+	 * For use by parsers and reparsers only, while list is being created.
+	 * 
+	 */
+	public ITextRegion remove(int index);
+
+	/**
+	 * Removes the region.
+	 * 
+	 * For use by parsers and reparsers only, while list is being created.
+	 * 
+	 */
+	public void remove(ITextRegion region);
+
+
+	/**
+	 * Removes all regionList from this list.
+	 * 
+	 * For use by parsers and reparsers only, while list is being created.
+	 * 
+	 */
+	public void removeAll(ITextRegionList regionList);
+
+	/**
+	 * Returns the size of the list.
+	 * 
+	 * @return the size of the list.
+	 */
+	public int size();
+
+
+	/**
+	 * Creates and returns the regions in an array. No assumptions should be
+	 * made if the regions in the array are clones are same instance of
+	 * original region.
+	 * 
+	 * ISSUE: do we need to specify if cloned copies or not?
+	 * 
+	 * @return an array of regions.
+	 */
+	public ITextRegion[] toArray();
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java
new file mode 100644
index 0000000..c4821c1
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java
@@ -0,0 +1,2979 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2011 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Møller - initial IDocumentExtension4 support - #102822
+ *                           (see also #239115)
+ *     David Carver (Intalio) - bug 300434 - Make inner classes static where possible
+ *     David Carver (Intalio) - bug 300443 - some constants aren't static final
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPartitioningException;
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.DefaultLineTracker;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.DocumentPartitioningChangedEvent;
+import org.eclipse.jface.text.DocumentRewriteSession;
+import org.eclipse.jface.text.DocumentRewriteSessionEvent;
+import org.eclipse.jface.text.DocumentRewriteSessionType;
+import org.eclipse.jface.text.FindReplaceDocumentAdapter;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension;
+import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.IDocumentPartitionerExtension;
+import org.eclipse.jface.text.IDocumentPartitionerExtension2;
+import org.eclipse.jface.text.IDocumentPartitionerExtension3;
+import org.eclipse.jface.text.IDocumentPartitioningListener;
+import org.eclipse.jface.text.IDocumentPartitioningListenerExtension;
+import org.eclipse.jface.text.IDocumentPartitioningListenerExtension2;
+import org.eclipse.jface.text.IDocumentRewriteSessionListener;
+import org.eclipse.jface.text.ILineTracker;
+import org.eclipse.jface.text.ILineTrackerExtension;
+import org.eclipse.jface.text.IPositionUpdater;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextStore;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TypedRegion;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.document.StructuredDocumentFactory;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.provisional.events.AboutToBeChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.IModelAboutToBeChangedListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredPartitioning;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextReParser;
+import org.eclipse.wst.sse.core.internal.text.rules.StructuredTextPartitioner;
+import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager;
+import org.eclipse.wst.sse.core.internal.undo.StructuredTextUndoManager;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+
+
+/**
+ * The standard implementation of structured document.
+ */
+public class BasicStructuredDocument implements IStructuredDocument, IDocumentExtension, IDocumentExtension3, IDocumentExtension4, CharSequence, IRegionComparible {
+
+	/**
+	 * This ThreadLocal construct is used so each thread can maintain its only
+	 * pointer to the double linked list that manages the documents regions.
+	 * The only thing we "gaurd" for is that a previously cached region has
+	 * been deleted.
+	 * 
+	 * The object that is kept in the thread local's map, is just a pointer to
+	 * an array position. That's because the object there needs to be "free"
+	 * from references to other objects, or it will not be garbage collected.
+	 */
+	private class CurrentDocumentRegionCache {
+		// I'm assuming for now there would never be so many threads that
+		// this arrayList needs to be bounded, or 'cleaned up'.
+		// this assumption should be tested in practice and long running
+		// jobs -- found not to be a good assumption. See below.
+		private List cachedRegionPositionArray = Collections.synchronizedList(new ArrayList());
+		private final boolean DEBUG = false;
+		private static final int MAX_SIZE = 50;
+
+
+		private ThreadLocal threadLocalCachePosition = new ThreadLocal();
+
+		IStructuredDocumentRegion get() {
+			IStructuredDocumentRegion region = null;
+			int pos = getThreadLocalPosition();
+			try {
+				region = (IStructuredDocumentRegion) cachedRegionPositionArray.get(pos);
+			}
+			catch (IndexOutOfBoundsException e) {
+				// even though the cachedRegionPosition is synchronized,
+				// that just means each access is syncronized, its
+				// still possible for another thread to cause it to
+				// be cleared, after this thread gets it position.
+				// So, if that happens, all we can do is reset to beginning.
+				// This should be extremely rare (in other words, probably
+				// not worth using synchronized blocks
+				// to access cachedRegionPositionArray.
+				reinitThreadLocalPosition();
+				resetToInitialState();
+			}
+			if (region == null) {
+				region = resetToInitialState();
+			}
+			else
+			// region not null
+			if (region.isDeleted()) {
+				region = resetToInitialState();
+			}
+			return region;
+		}
+
+		private int getThreadLocalPosition() {
+			Object threadLocalObject = threadLocalCachePosition.get();
+			int pos = -1;
+			if (threadLocalObject == null) {
+
+				pos = reinitThreadLocalPosition();
+			}
+			else {
+				pos = ((Integer) threadLocalObject).intValue();
+			}
+			return pos;
+		}
+
+		/**
+		 * @return
+		 */
+		private int reinitThreadLocalPosition() {
+			Integer position;
+			int pos;
+			// TODO_future: think of a better solution that doesn't
+			// require this kludge. This is especially required because
+			// some infrasture, such as reconciler, actually null out
+			// their thread object and recreate it, 500 msecs later
+			// (approximately).
+			// Note: the likely solution in future is to clear after every
+			// heavy use of getCachedRegion, such as in creating node
+			// lists, or reparsing or partioning.
+			if (cachedRegionPositionArray.size() > MAX_SIZE) {
+				cachedRegionPositionArray.clear();
+				if (DEBUG) {
+					System.out.println("cachedRegionPositionArray cleared at size " + MAX_SIZE); //$NON-NLS-1$
+				}
+			}
+			position = new Integer(cachedRegionPositionArray.size());
+			threadLocalCachePosition.set(position);
+			cachedRegionPositionArray.add(position.intValue(), null);
+			pos = position.intValue();
+			return pos;
+		}
+
+		private IStructuredDocumentRegion resetToInitialState() {
+			IStructuredDocumentRegion region;
+			region = getFirstStructuredDocumentRegion();
+			set(region);
+			return region;
+		}
+
+		void set(IStructuredDocumentRegion region) {
+			try {
+				int pos = getThreadLocalPosition();
+				cachedRegionPositionArray.set(pos, region);
+			}
+			catch (IndexOutOfBoundsException e) {
+				// even though the cachedRegionPosition is synchronized,
+				// that just means each access is syncronized, its
+				// still possible for another thread to cause it to
+				// be cleared, after this thread gets it position.
+				// So, if that happens, all we can do is reset to beginning.
+				// This should be extremely rare (in other words, probably
+				// not worth using synchronized blocks
+				// to access cachedRegionPositionArray.
+				reinitThreadLocalPosition();
+				resetToInitialState();
+			}
+		}
+	}
+
+	/**
+	 * This NullDocumentEvent is used to complete the "aboutToChange" and
+	 * "changed" cycle, when in fact the original change is no longer valid.
+	 * The only known (valid) case of this is when a model re-initialize takes
+	 * place, which causes setText to be called in the middle of some previous
+	 * change. [This architecture will be improved in future].
+	 */
+	public class NullDocumentEvent extends DocumentEvent {
+		public NullDocumentEvent() {
+			this(BasicStructuredDocument.this, 0, 0, ""); //$NON-NLS-1$
+		}
+
+		private NullDocumentEvent(IDocument doc, int offset, int length, String text) {
+			super(doc, offset, length, text);
+		}
+	}
+
+	static class RegisteredReplace {
+		/** The owner of this replace operation. */
+		IDocumentListener fOwner;
+		/** The replace operation */
+		IDocumentExtension.IReplace fReplace;
+
+		/**
+		 * Creates a new bundle object.
+		 * 
+		 * @param owner
+		 *            the document listener owning the replace operation
+		 * @param replace
+		 *            the replace operation
+		 */
+		RegisteredReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) {
+			fOwner = owner;
+			fReplace = replace;
+		}
+	}
+
+	/**
+	 * these control variable isn't mark as 'final' since there's some unit
+	 * tests that manipulate it. For final product, it should be.
+	 */
+
+	private static boolean USE_LOCAL_THREAD = true;
+
+	/**
+	 * purely for debugging/performance measurements In practice, would always
+	 * be 'true'. (and should never be called by called by clients). Its not
+	 * 'final' or private just so it can be varied during
+	 * debugging/performance measurement runs.
+	 * 
+	 * @param use_local_thread
+	 */
+	public static void setUSE_LOCAL_THREAD(final boolean use_local_thread) {
+		USE_LOCAL_THREAD = use_local_thread;
+	}
+
+	private IStructuredDocumentRegion cachedDocumentRegion;
+	private EncodingMemento encodingMemento;
+	private boolean fAcceptPostNotificationReplaces = true;
+	private CurrentDocumentRegionCache fCurrentDocumentRegionCache;
+	private DocumentEvent fDocumentEvent;
+	private IDocumentListener[] fDocumentListeners;
+
+	/**
+	 * The registered document partitioners.
+	 */
+	private Map fDocumentPartitioners;
+	/** The registered document partitioning listeners */
+	private List fDocumentPartitioningListeners;
+	private IStructuredDocumentRegion firstDocumentRegion;
+	private RegionParser fParser;
+	private GenericPositionManager fPositionManager;
+	private List fPostNotificationChanges;
+	private IDocumentListener[] fPrenotifiedDocumentListeners;
+	private int fReentranceCount = 0;
+	private IStructuredTextReParser fReParser;
+	private int fStoppedCount = 0;
+
+	private ITextStore fStore;
+	private Object[] fStructuredDocumentAboutToChangeListeners;
+	private Object[] fStructuredDocumentChangedListeners;
+	private Object[] fStructuredDocumentChangingListeners;
+
+	private List fDocumentRewriteSessionListeners;
+
+	private ILineTracker fTracker;
+	private IStructuredTextUndoManager fUndoManager;
+	private IStructuredDocumentRegion lastDocumentRegion;
+
+	private byte[] listenerLock = new byte[0];
+	private NullDocumentEvent NULL_DOCUMENT_EVENT;
+
+	/**
+	 * Theoretically, a document can contain mixed line delimiters, but the
+	 * user's preference is usually to be internally consistent.
+	 */
+	private String fInitialLineDelimiter;
+	private static final String READ_ONLY_REGIONS_CATEGORY = "_READ_ONLY_REGIONS_CATEGORY_"; //$NON-NLS-1$
+	/**
+	 * Current rewrite session, or none if not presently rewriting.
+	 */
+	private DocumentRewriteSession fActiveRewriteSession;
+	/**
+	 * Last modification stamp, automatically updated on change.
+	 */
+	private long fModificationStamp;
+	/**
+	 * Keeps track of next modification stamp.
+	 */
+	private long fNextModificationStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
+	/**
+	 * debug variable only
+	 * 
+	 * @param parser
+	 */
+	private long startStreamTime;
+	/**
+	 * debug variable only
+	 * 
+	 * @param parser
+	 */
+	private long startTime;
+
+	public BasicStructuredDocument() {
+		super();
+		fCurrentDocumentRegionCache = new CurrentDocumentRegionCache();
+		setTextStore(new StructuredDocumentTextStore(50, 300));
+		setLineTracker(new DefaultLineTracker());
+		NULL_DOCUMENT_EVENT = new NullDocumentEvent();
+
+		internal_addPositionCategory(READ_ONLY_REGIONS_CATEGORY);
+		internal_addPositionUpdater(new DeleteEqualPositionUpdater(READ_ONLY_REGIONS_CATEGORY));
+
+	}
+
+	/**
+	 * This is the primary way to get a new structuredDocument. Its best to
+	 * use the factory methods in ModelManger to create a new
+	 * IStructuredDocument, since it will get and initialize the parser
+	 * according to the desired content type.
+	 */
+	public BasicStructuredDocument(RegionParser parser) {
+		this();
+		Assert.isNotNull(parser, "Program Error: IStructuredDocument can not be created with null parser"); //$NON-NLS-1$
+		// go through setter in case there is side effects
+		internal_setParser(parser);
+	}
+
+	private void _clearDocumentEvent() {
+		// no hard and fast requirement to null out ... just seems like
+		// a good idea, since we are done with it.
+		fDocumentEvent = null;
+	}
+
+	private void _fireDocumentAboutToChange(Object[] listeners) {
+		// most DocumentAboutToBeChanged listeners do not anticipate
+		// DocumentEvent == null. So make sure documentEvent is not
+		// null. (this should never happen, yet it does sometimes)
+		if (fDocumentEvent == null) {
+			fDocumentEvent = new NullDocumentEvent();
+		}
+		// we must assign listeners to local variable, since the add and
+		// remove
+		// listner
+		// methods can change the actual instance of the listener array from
+		// another thread
+		if (listeners != null) {
+			Object[] holdListeners = listeners;
+			// Note: the docEvent is created in replaceText API
+			// fire
+			for (int i = 0; i < holdListeners.length; i++) {
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					startTime = System.currentTimeMillis();
+				}
+				// safeguard from listeners that throw exceptions
+				try {
+					// this is a safe cast, since addListners requires a
+					// IStructuredDocumentListener
+					((IDocumentListener) holdListeners[i]).documentAboutToBeChanged(fDocumentEvent);
+				}
+				catch (Exception exception) {
+					Logger.logException(exception);
+				}
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					long stopTime = System.currentTimeMillis();
+					System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$
+				}
+			}
+		}
+	}
+
+	private void notifyDocumentPartitionersAboutToChange(DocumentEvent documentEvent) {
+		if (fDocumentPartitioners != null) {
+			Iterator e = fDocumentPartitioners.values().iterator();
+			while (e.hasNext()) {
+				IDocumentPartitioner p = (IDocumentPartitioner) e.next();
+				// safeguard from listeners that throw exceptions
+				try {
+					p.documentAboutToBeChanged(documentEvent);
+				}
+				catch (Exception exception) {
+					Logger.logException(exception);
+				}
+			}
+		}
+	}
+
+	private void _fireDocumentChanged(Object[] listeners, StructuredDocumentEvent event) {
+
+		// we must assign listeners to local variable, since the add and
+		// remove
+		// listner
+		// methods can change the actual instance of the listener array from
+		// another thread
+		if (listeners != null) {
+			Object[] holdListeners = listeners;
+			// NOTE: document event is created in replace Text API and setText
+			// API
+			// now fire
+			for (int i = 0; i < holdListeners.length; i++) {
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					startTime = System.currentTimeMillis();
+				}
+
+				// safeguard from listeners that throw exceptions
+				try {
+					// this is a safe cast, since addListners requires a
+					// IStructuredDocumentListener
+					// Notes: fDocumentEvent can be "suddenly" null, if one of
+					// the
+					// previous changes
+					// caused a "setText" to be called. The only known case of
+					// this
+					// is a model reset
+					// due to page directive changing. Eventually we should
+					// change
+					// archetecture to have
+					// event que and be able to "cancel" pending events, but
+					// for
+					// now, we'll just pass a
+					// NullDocumentEvent. By the way, it is important to send
+					// something, since clients might
+					// have indeterminant state due to "aboutToChange" being
+					// sent
+					// earlier.
+					if (fDocumentEvent == null) {
+						((IDocumentListener) holdListeners[i]).documentChanged(NULL_DOCUMENT_EVENT);
+					}
+					else {
+						((IDocumentListener) holdListeners[i]).documentChanged(fDocumentEvent);
+					}
+				}
+				catch (Exception exception) {
+					Logger.logException(exception);
+				}
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					long stopTime = System.currentTimeMillis();
+					System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$
+				}
+			}
+		}
+	}
+
+	private void notifyDocumentPartitionersDocumentChanged(DocumentEvent documentEvent) {
+		if (fDocumentPartitioners != null) {
+			Iterator e = fDocumentPartitioners.values().iterator();
+			while (e.hasNext()) {
+				IDocumentPartitioner p = (IDocumentPartitioner) e.next();
+				// safeguard from listeners that throw exceptions
+				try {
+					if (p instanceof IDocumentPartitionerExtension) {
+						// IRegion changedPartion =
+						((IDocumentPartitionerExtension) p).documentChanged2(documentEvent);
+					}
+					else {
+						p.documentChanged(documentEvent);
+					}
+				}
+				catch (Exception exception) {
+					Logger.logException(exception);
+				}
+			}
+		}
+	}
+
+
+	private void _fireEvent(Object[] listeners, NoChangeEvent event) {
+		// we must assign listeners to local variable, since the add and
+		// remove
+		// listner
+		// methods can change the actual instance of the listener array from
+		// another thread
+		if (listeners != null) {
+			Object[] holdListeners = listeners;
+			for (int i = 0; i < holdListeners.length; i++) {
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					startTime = System.currentTimeMillis();
+				}
+				// safeguard from listeners that throw exceptions
+				try {
+					// this is a safe cast, since addListners requires a
+					// IStructuredDocumentListener
+					((IStructuredDocumentListener) holdListeners[i]).noChange(event);
+				}
+				catch (Exception exception) {
+					Logger.logException(exception);
+				}
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					long stopTime = System.currentTimeMillis();
+					System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$
+				}
+			}
+		}
+	}
+
+	private void _fireEvent(Object[] listeners, RegionChangedEvent event) {
+		// we must assign listeners to local variable, since the add and
+		// remove
+		// listner
+		// methods can change the actual instance of the listener array from
+		// another thread
+		if (listeners != null) {
+			Object[] holdListeners = listeners;
+			for (int i = 0; i < holdListeners.length; i++) {
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					startTime = System.currentTimeMillis();
+				}
+				// safeguard from listeners that throw exceptions
+				try {
+					// this is a safe cast, since addListners requires a
+					// IStructuredDocumentListener
+					((IStructuredDocumentListener) holdListeners[i]).regionChanged(event);
+				}
+				catch (Exception exception) {
+					Logger.logException(exception);
+				}
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					long stopTime = System.currentTimeMillis();
+					System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$
+				}
+			}
+		}
+	}
+
+	private void _fireEvent(Object[] listeners, RegionsReplacedEvent event) {
+		// we must assign listeners to local variable, since the add and
+		// remove
+		// listner
+		// methods can change the actual instance of the listener array from
+		// another thread
+		if (listeners != null) {
+			Object[] holdListeners = listeners;
+			for (int i = 0; i < holdListeners.length; i++) {
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					startTime = System.currentTimeMillis();
+				}
+				// safeguard from listeners that throw exceptions
+				try {
+					// this is a safe cast, since addListners requires a
+					// IStructuredDocumentListener
+					((IStructuredDocumentListener) holdListeners[i]).regionsReplaced(event);
+				}
+				catch (Exception exception) {
+					Logger.logException(exception);
+				}
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					long stopTime = System.currentTimeMillis();
+					System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$
+				}
+			}
+		}
+	}
+
+	private void _fireEvent(Object[] listeners, StructuredDocumentRegionsReplacedEvent event) {
+		// we must assign listeners to local variable, since the add and
+		// remove
+		// listner
+		// methods can change the actual instance of the listener array from
+		// another thread
+		if (listeners != null) {
+			Object[] holdListeners = listeners;
+			for (int i = 0; i < holdListeners.length; i++) {
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					startTime = System.currentTimeMillis();
+				}
+				// safeguard from listeners that throw exceptions
+				try {
+					// this is a safe cast, since addListners requires a
+					// IStructuredDocumentListener
+					((IStructuredDocumentListener) holdListeners[i]).nodesReplaced(event);
+				}
+				catch (Exception exception) {
+					Logger.logException(exception);
+				}
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					long stopTime = System.currentTimeMillis();
+					System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$
+				}
+			}
+		}
+	}
+
+	private void _fireStructuredDocumentAboutToChange(Object[] listeners) {
+		// we must assign listeners to local variable, since the add and
+		// remove
+		// listner
+		// methods can change the actual instance of the listener array from
+		// another thread
+		if (listeners != null) {
+			Object[] holdListeners = listeners;
+			// Note: the docEvent is created in replaceText API
+			// fire
+			for (int i = 0; i < holdListeners.length; i++) {
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					startTime = System.currentTimeMillis();
+				}
+				// safeguard from listeners that throw exceptions
+				try {
+					// notice the AboutToBeChangedEvent is created from the
+					// DocumentEvent, since it is (nearly)
+					// the same information. ?What to do about
+					// originalRequester?
+					if (fDocumentEvent == null) {
+						fDocumentEvent = new NullDocumentEvent();
+					}
+					AboutToBeChangedEvent aboutToBeChangedEvent = new AboutToBeChangedEvent(this, null, fDocumentEvent.getText(), fDocumentEvent.getOffset(), fDocumentEvent.getLength());
+					// this is a safe cast, since addListners requires a
+					// IStructuredDocumentListener
+					((IModelAboutToBeChangedListener) holdListeners[i]).modelAboutToBeChanged(aboutToBeChangedEvent);
+				}
+				catch (Exception exception) {
+					Logger.logException(exception);
+				}
+				if (Debug.perfTest || Debug.perfTestStructuredDocumentEventOnly) {
+					long stopTime = System.currentTimeMillis();
+					System.out.println("\n\t\t\t\t IStructuredDocument::fireStructuredDocumentEvent. Time was " + (stopTime - startTime) + " msecs to fire NewModelEvent to instance of " + holdListeners[i].getClass()); //$NON-NLS-2$//$NON-NLS-1$
+				}
+			}
+		}
+	}
+
+	protected void acquireLock() {
+		// do nothing here in super class
+	}
+
+	/**
+	 * addModelAboutToBeChangedListener method comment.
+	 */
+	public void addDocumentAboutToChangeListener(IModelAboutToBeChangedListener listener) {
+		synchronized (listenerLock) {
+
+			// make sure listener is not already in listening
+			// (and if it is, print a warning to aid debugging, if needed)
+			if (!Utilities.contains(fStructuredDocumentAboutToChangeListeners, listener)) {
+				int oldSize = 0;
+				if (fStructuredDocumentAboutToChangeListeners != null) {
+					// normally won't be null, but we need to be sure, for
+					// first
+					// time through
+					oldSize = fStructuredDocumentAboutToChangeListeners.length;
+				}
+				int newSize = oldSize + 1;
+				Object[] newListeners = new Object[newSize];
+				if (fStructuredDocumentAboutToChangeListeners != null) {
+					System.arraycopy(fStructuredDocumentAboutToChangeListeners, 0, newListeners, 0, oldSize);
+				}
+				// add listener to last position
+				newListeners[newSize - 1] = listener;
+				//
+				// now switch new for old
+				fStructuredDocumentAboutToChangeListeners = newListeners;
+				//
+			}
+		}
+	}
+
+	/**
+	 * The StructuredDocumentListners and ModelChagnedListeners are very
+	 * similar. They both receive identical events. The difference is the
+	 * timing. The "pure" StructuredDocumentListners are notified after the
+	 * structuredDocument has been changed, but before other, related models
+	 * may have been changed such as the Structural Model. The Structural
+	 * model is in fact itself a "pure" StructuredDocumentListner. The
+	 * ModelChangedListeners can rest assured that all models and data have
+	 * been updated from the change by the tiem they are notified. This is
+	 * especially important for the text widget, for example, which may rely
+	 * on both structuredDocument and structural model information.
+	 */
+	public void addDocumentChangedListener(IStructuredDocumentListener listener) {
+		synchronized (listenerLock) {
+
+			if (Debug.debugStructuredDocument) {
+				System.out.println("IStructuredDocument::addModelChangedListener. Request to add an instance of " + listener.getClass() + " as a listener on structuredDocument."); //$NON-NLS-2$//$NON-NLS-1$
+			}
+			// make sure listener is not already in listening
+			// (and if it is, print a warning to aid debugging, if needed)
+			if (Utilities.contains(fStructuredDocumentChangedListeners, listener)) {
+				if (Debug.displayWarnings) {
+					System.out.println("IStructuredDocument::addModelChangedListener. listener " + listener + " was addeded more than once. "); //$NON-NLS-2$//$NON-NLS-1$
+				}
+			}
+			else {
+				if (Debug.debugStructuredDocument) {
+					System.out.println("IStructuredDocument::addModelChangedListener. Adding an instance of " + listener.getClass() + " as a listener on structuredDocument."); //$NON-NLS-2$//$NON-NLS-1$
+				}
+				int oldSize = 0;
+				if (fStructuredDocumentChangedListeners != null) {
+					// normally won't be null, but we need to be sure, for
+					// first
+					// time through
+					oldSize = fStructuredDocumentChangedListeners.length;
+				}
+				int newSize = oldSize + 1;
+				Object[] newListeners = new Object[newSize];
+				if (fStructuredDocumentChangedListeners != null) {
+					System.arraycopy(fStructuredDocumentChangedListeners, 0, newListeners, 0, oldSize);
+				}
+				// add listener to last position
+				newListeners[newSize - 1] = listener;
+				//
+				// now switch new for old
+				fStructuredDocumentChangedListeners = newListeners;
+				//
+				// when a listener is added,
+				// send the new model event to that one particular listener,
+				// so it
+				// can initialize itself with the current state of the model
+				// listener.newModel(new NewModelEvent(this, listener));
+			}
+		}
+	}
+
+	public void addDocumentChangingListener(IStructuredDocumentListener listener) {
+		synchronized (listenerLock) {
+
+			if (Debug.debugStructuredDocument) {
+				System.out.println("IStructuredDocument::addStructuredDocumentListener. Request to add an instance of " + listener.getClass() + " as a listener on structuredDocument."); //$NON-NLS-2$//$NON-NLS-1$
+			}
+			// make sure listener is not already in listening
+			// (and if it is, print a warning to aid debugging, if needed)
+			if (Utilities.contains(fStructuredDocumentChangingListeners, listener)) {
+				if (Debug.displayWarnings) {
+					System.out.println("IStructuredDocument::addStructuredDocumentListener. listener " + listener + " was addeded more than once. "); //$NON-NLS-2$//$NON-NLS-1$
+				}
+			}
+			else {
+				if (Debug.debugStructuredDocument) {
+					System.out.println("IStructuredDocument::addStructuredDocumentListener. Adding an instance of " + listener.getClass() + " as a listener on structuredDocument."); //$NON-NLS-2$//$NON-NLS-1$
+				}
+				int oldSize = 0;
+				if (fStructuredDocumentChangingListeners != null) {
+					// normally won't be null, but we need to be sure, for
+					// first
+					// time through
+					oldSize = fStructuredDocumentChangingListeners.length;
+				}
+				int newSize = oldSize + 1;
+				Object[] newListeners = new Object[newSize];
+				if (fStructuredDocumentChangingListeners != null) {
+					System.arraycopy(fStructuredDocumentChangingListeners, 0, newListeners, 0, oldSize);
+				}
+				// add listener to last position
+				newListeners[newSize - 1] = listener;
+				//
+				// now switch new for old
+				fStructuredDocumentChangingListeners = newListeners;
+				//
+				// when a listener is added,
+				// send the new model event to that one particular listener,
+				// so it
+				// can initialize itself with the current state of the model
+				// listener.newModel(new NewModelEvent(this, listener));
+			}
+		}
+	}
+
+	/**
+	 * We manage our own document listners, instead of delegating to our
+	 * parentDocument, so we can fire at very end (and not when the
+	 * parentDocument changes).
+	 * 
+	 */
+	public void addDocumentListener(IDocumentListener listener) {
+		synchronized (listenerLock) {
+
+			// make sure listener is not already in listening
+			// (and if it is, print a warning to aid debugging, if needed)
+			if (!Utilities.contains(fDocumentListeners, listener)) {
+				int oldSize = 0;
+				if (fDocumentListeners != null) {
+					// normally won't be null, but we need to be sure, for
+					// first
+					// time through
+					oldSize = fDocumentListeners.length;
+				}
+				int newSize = oldSize + 1;
+				IDocumentListener[] newListeners = null;
+				newListeners = new IDocumentListener[newSize];
+				if (fDocumentListeners != null) {
+					System.arraycopy(fDocumentListeners, 0, newListeners, 0, oldSize);
+				}
+				// add listener to last position
+				newListeners[newSize - 1] = listener;
+				// now switch new for old
+				fDocumentListeners = newListeners;
+			}
+		}
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#addDocumentPartitioningListener(org.eclipse.jface.text.IDocumentPartitioningListener)
+	 * 
+	 * Registers the document partitioning listener with the document. After
+	 * registration the IDocumentPartitioningListener is informed about each
+	 * partition change cause by a document manipulation. If a document
+	 * partitioning listener is also a document listener, the following
+	 * notification sequence is guaranteed if a document manipulation changes
+	 * the document partitioning: 1)
+	 * listener.documentAboutToBeChanged(DocumentEvent); 2)
+	 * listener.documentPartitioningChanged(); 3)
+	 * listener.documentChanged(DocumentEvent); If the listener is already
+	 * registered nothing happens.
+	 * 
+	 * @see IDocumentPartitioningListener
+	 */
+
+	public void addDocumentPartitioningListener(IDocumentPartitioningListener listener) {
+		synchronized (listenerLock) {
+
+			Assert.isNotNull(listener);
+			if (fDocumentPartitioningListeners == null) {
+				fDocumentPartitioningListeners = new ArrayList(1);
+			}
+			if (!fDocumentPartitioningListeners.contains(listener))
+				fDocumentPartitioningListeners.add(listener);
+		}
+	}
+
+	/**
+	 * Adds the position to the document's default position category. The
+	 * default category must be specified by the implementer. A position that
+	 * has been added to a position category is updated at each change applied
+	 * to the document.
+	 * 
+	 * @exception BadLocationException
+	 *                If position is not a valid range in the document
+	 */
+	public void addPosition(Position position) throws BadLocationException {
+		getPositionManager().addPosition(position);
+	}
+
+	/**
+	 * @see IDocument#addPosition
+	 * @exception BadLocationException
+	 *                If position is not a valid range in the document
+	 * @exception BadPositionCategoryException
+	 *                If the category is not defined for the document
+	 */
+	public void addPosition(String category, Position position) throws BadLocationException, BadPositionCategoryException {
+		getPositionManager().addPosition(category, position);
+	}
+
+	/**
+	 * @see IDocument#addPositionCategory
+	 */
+	public void addPositionCategory(String category) {
+		internal_addPositionCategory(category);
+	}
+
+	/**
+	 * @see IDocument#addPositionUpdater
+	 */
+	public void addPositionUpdater(IPositionUpdater updater) {
+		internal_addPositionUpdater(updater);
+	}
+
+	/**
+	 * Adds the given document listener as one which is notified before those
+	 * document listeners added with <code>addDocumentListener</code> are
+	 * notified. If the given listener is also registered using
+	 * <code>addDocumentListener</code> it will be notified twice. If the
+	 * listener is already registered nothing happens.
+	 * <p>
+	 * 
+	 * This method is not for public use, it may only be called by
+	 * implementers of <code>IDocumentAdapter</code> and only if those
+	 * implementers need to implement <code>IDocumentListener</code>.
+	 * 
+	 * @param documentAdapter
+	 *            the listener to be added as prenotified document listener
+	 */
+	public void addPrenotifiedDocumentListener(IDocumentListener documentAdapter) {
+		synchronized (listenerLock) {
+
+			if (fPrenotifiedDocumentListeners != null) {
+				int previousSize = fPrenotifiedDocumentListeners.length;
+				IDocumentListener[] listeners = new IDocumentListener[previousSize + 1];
+				System.arraycopy(fPrenotifiedDocumentListeners, 0, listeners, 0, previousSize);
+				listeners[previousSize] = documentAdapter;
+				fPrenotifiedDocumentListeners = listeners;
+			}
+			else {
+				fPrenotifiedDocumentListeners = new IDocumentListener[1];
+				fPrenotifiedDocumentListeners[0] = documentAdapter;
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.CharSequence#charAt(int)
+	 */
+	public char charAt(int arg0) {
+		try {
+			return getChar(0);
+		}
+		catch (BadLocationException e) {
+			throw new IndexOutOfBoundsException();
+		}
+	}
+
+	/**
+	 * This form of the API removes all read only positions, as should be done
+	 * we 'setText' is called. Note: an alternative algorithm may simply
+	 * remove the category (and it would get added back in later, if/when
+	 * readonly regions added.
+	 */
+	private void clearReadOnly() {
+		Position[] positions = null;
+		try {
+			positions = getPositions(READ_ONLY_REGIONS_CATEGORY);
+		}
+		catch (BadPositionCategoryException e) {
+			Logger.logException("program error: should never occur", e); //$NON-NLS-1$
+		}
+		for (int i = 0; i < positions.length; i++) {
+			Position position = positions[i];
+			// note we don't fire the "about to change" or "changed" events,
+			// since presumably, text is all going away and being replaced
+			// anyway.
+			position.delete();
+		}
+	}
+
+
+	public void clearReadOnly(int startOffset, int length) {
+		// TODO DW I still need to implement smarter algorithm that
+		// adust existing RO regions, if needed. For now, I'll just
+		// remove any that overlap.
+		try {
+			Position[] positions = getPositions(READ_ONLY_REGIONS_CATEGORY);
+			for (int i = 0; i < positions.length; i++) {
+				Position position = positions[i];
+				if (position.overlapsWith(startOffset, length)) {
+					String effectedText = this.get(startOffset, length);
+					// fDocumentEvent = new DocumentEvent(this, startOffset,
+					// length, effectedText);
+					fireReadOnlyAboutToBeChanged();
+					position.delete();
+					NoChangeEvent noChangeEvent = new NoChangeEvent(this, null, effectedText, startOffset, length);
+					noChangeEvent.reason = NoChangeEvent.READ_ONLY_STATE_CHANGE;
+					fireReadOnlyStructuredDocumentEvent(noChangeEvent);
+				}
+			}
+		}
+		catch (BadPositionCategoryException e) {
+			// just means no readonly regions been defined yet
+			// so nothing to do.
+		}
+	}
+
+	/**
+	 * Computes the index at which a <code>Position</code> with the
+	 * specified offset would be inserted into the given category. As the
+	 * ordering inside a category only depends on the offset, the index must
+	 * be choosen to be the first of all positions with the same offset.
+	 * 
+	 * @param category
+	 *            the category in which would be added
+	 * @param offset
+	 *            the position offset to be considered
+	 * @return the index into the category
+	 * @exception BadLocationException
+	 *                if offset is invalid in this document
+	 * @exception BadPositionCategoryException
+	 *                if category is undefined in this document
+	 */
+	public int computeIndexInCategory(String category, int offset) throws org.eclipse.jface.text.BadPositionCategoryException, org.eclipse.jface.text.BadLocationException {
+		return getPositionManager().computeIndexInCategory(category, offset);
+	}
+
+	/**
+	 * Computes the number of lines in the given text. For a given implementer
+	 * of this interface this method returns the same result as
+	 * <code>set(text); getNumberOfLines()</code>.
+	 * 
+	 * @param text
+	 *            the text whose number of lines should be computed
+	 * @return the number of lines in the given text
+	 */
+	public int computeNumberOfLines(String text) {
+		return getTracker().computeNumberOfLines(text);
+	}
+
+	/**
+	 * Computes the partitioning of the given document range using the
+	 * document's partitioner.
+	 * 
+	 * @param offset
+	 *            the document offset at which the range starts
+	 * @param length
+	 *            the length of the document range
+	 * @return a specification of the range's partitioning
+	 * @throws BadLocationException
+	 * @throws BadPartitioningException
+	 */
+	public ITypedRegion[] computePartitioning(int offset, int length) throws BadLocationException {
+		ITypedRegion[] typedRegions = null;
+		try {
+			typedRegions = computePartitioning(IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING, offset, length, false);
+		}
+		catch (BadPartitioningException e) {
+			// impossible in this context
+			throw new Error(e);
+		}
+		if (typedRegions == null) {
+			typedRegions = new ITypedRegion[0];
+		}
+		return typedRegions;
+	}
+
+
+	public ITypedRegion[] computePartitioning(String partitioning, int offset, int length, boolean includeZeroLengthPartitions) throws BadLocationException, BadPartitioningException {
+		if ((0 > offset) || (0 > length) || (offset + length > getLength()))
+			throw new BadLocationException();
+
+		IDocumentPartitioner partitioner = getDocumentPartitioner(partitioning);
+
+		if (partitioner instanceof IDocumentPartitionerExtension2)
+			return ((IDocumentPartitionerExtension2) partitioner).computePartitioning(offset, length, includeZeroLengthPartitions);
+		else if (partitioner != null)
+			return partitioner.computePartitioning(offset, length);
+		else if (IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING.equals(partitioning))
+			return new TypedRegion[]{new TypedRegion(offset, length, DEFAULT_CONTENT_TYPE)};
+		else
+			throw new BadPartitioningException();
+	}
+
+	/**
+	 * @see IDocument#containsPosition
+	 */
+	public boolean containsPosition(String category, int offset, int length) {
+		return getPositionManager().containsPosition(category, offset, length);
+	}
+
+	/**
+	 * @see IDocument#containsPositionCategory
+	 */
+	public boolean containsPositionCategory(String category) {
+		return getPositionManager().containsPositionCategory(category);
+	}
+
+	public boolean containsReadOnly(int startOffset, int length) {
+		boolean result = false;
+		try {
+			Position[] positions = getPositions(READ_ONLY_REGIONS_CATEGORY);
+			for (int i = 0; i < positions.length; i++) {
+				Position position = positions[i];
+				if (position.overlapsWith(startOffset, length)) {
+					result = true;
+					break;
+				}
+			}
+		}
+		catch (BadPositionCategoryException e) {
+			// just means no readonly regions been defined yet
+			// so obviously false
+			result = false;
+		}
+		return result;
+	}
+
+	private void executePostNotificationChanges() {
+		if (fStoppedCount > 0)
+			return;
+		while (fPostNotificationChanges != null) {
+			List changes = fPostNotificationChanges;
+			fPostNotificationChanges = null;
+			Iterator e = changes.iterator();
+			while (e.hasNext()) {
+				RegisteredReplace replace = (RegisteredReplace) e.next();
+				replace.fReplace.perform(this, replace.fOwner);
+			}
+		}
+	}
+
+	private void fireDocumentAboutToChanged() {
+		// most DocumentAboutToBeChanged listeners do not anticipate
+		// DocumentEvent == null. So make sure documentEvent is not
+		// null. (this should never happen, yet it does sometimes)
+		if (fDocumentEvent == null) {
+			fDocumentEvent = new NullDocumentEvent();
+		}
+
+		_fireStructuredDocumentAboutToChange(fStructuredDocumentAboutToChangeListeners);
+		// Note: the docEvent is created in replaceText API! (or set Text)
+		_fireDocumentAboutToChange(fPrenotifiedDocumentListeners);
+		notifyDocumentPartitionersAboutToChange(fDocumentEvent);
+		_fireDocumentAboutToChange(fDocumentListeners);
+	}
+
+	/**
+	 * Fires the document partitioning changed notification to all registered
+	 * document partitioning listeners. Uses a robust iterator.
+	 * 
+	 * @param event
+	 *            the document partitioning changed event
+	 * 
+	 * @see IDocumentPartitioningListenerExtension2
+	 */
+	protected void fireDocumentPartitioningChanged(DocumentPartitioningChangedEvent event) {
+		if (fDocumentPartitioningListeners == null || fDocumentPartitioningListeners.size() == 0)
+			return;
+
+		List list = new ArrayList(fDocumentPartitioningListeners);
+		Iterator e = list.iterator();
+		while (e.hasNext()) {
+			IDocumentPartitioningListener l = (IDocumentPartitioningListener) e.next();
+			if (l instanceof IDocumentPartitioningListenerExtension2) {
+				IDocumentPartitioningListenerExtension2 extension2 = (IDocumentPartitioningListenerExtension2) l;
+				extension2.documentPartitioningChanged(event);
+			}
+			else if (l instanceof IDocumentPartitioningListenerExtension) {
+				IDocumentPartitioningListenerExtension extension = (IDocumentPartitioningListenerExtension) l;
+				extension.documentPartitioningChanged(this, event.getCoverage());
+			}
+			else {
+				l.documentPartitioningChanged(this);
+			}
+		}
+
+	}
+
+	private void fireReadOnlyAboutToBeChanged() {
+		_fireStructuredDocumentAboutToChange(fStructuredDocumentAboutToChangeListeners);
+		// Note: the docEvent is created in replaceText API! (or set Text)
+		// _fireDocumentAboutToChange(fPrenotifiedDocumentListeners);
+		// _fireDocumentAboutToChange(fDocumentListeners);
+	}
+
+	private void fireReadOnlyStructuredDocumentEvent(NoChangeEvent event) {
+		_fireEvent(fStructuredDocumentChangingListeners, event);
+		_fireEvent(fStructuredDocumentChangedListeners, event);
+		// _fireDocumentChanged(fPrenotifiedDocumentListeners, event);
+		// _fireDocumentChanged(fDocumentListeners, event);
+		// _clearDocumentEvent();
+	}
+
+	private void fireStructuredDocumentEvent(NoChangeEvent event) {
+		_fireEvent(fStructuredDocumentChangingListeners, event);
+		_fireEvent(fStructuredDocumentChangedListeners, event);
+		_fireDocumentChanged(fPrenotifiedDocumentListeners, event);
+		notifyDocumentPartitionersDocumentChanged(event);
+		_fireDocumentChanged(fDocumentListeners, event);
+		_clearDocumentEvent();
+	}
+
+	private void fireStructuredDocumentEvent(RegionChangedEvent event) {
+		_fireEvent(fStructuredDocumentChangingListeners, event);
+		_fireEvent(fStructuredDocumentChangedListeners, event);
+		_fireDocumentChanged(fPrenotifiedDocumentListeners, event);
+		notifyDocumentPartitionersDocumentChanged(event);
+		_fireDocumentChanged(fDocumentListeners, event);
+		_clearDocumentEvent();
+	}
+
+	private void fireStructuredDocumentEvent(RegionsReplacedEvent event) {
+		_fireEvent(fStructuredDocumentChangingListeners, event);
+		_fireEvent(fStructuredDocumentChangedListeners, event);
+		_fireDocumentChanged(fPrenotifiedDocumentListeners, event);
+		notifyDocumentPartitionersDocumentChanged(event);
+		_fireDocumentChanged(fDocumentListeners, event);
+		_clearDocumentEvent();
+	}
+
+	private void fireStructuredDocumentEvent(StructuredDocumentRegionsReplacedEvent event) {
+		_fireEvent(fStructuredDocumentChangingListeners, event);
+		_fireEvent(fStructuredDocumentChangedListeners, event);
+		_fireDocumentChanged(fPrenotifiedDocumentListeners, event);
+		notifyDocumentPartitionersDocumentChanged(event);
+		_fireDocumentChanged(fDocumentListeners, event);
+		_clearDocumentEvent();
+	}
+
+	/**
+	 * Returns the document's complete text.
+	 */
+	public String get() {
+		return getStore().get(0, getLength());
+	}
+
+	/**
+	 * Returns length characters from the document's text starting from the
+	 * specified position.
+	 * 
+	 * @throws BadLocationException
+	 * 
+	 * @exception BadLocationException
+	 *                If the range is not valid in the document
+	 */
+	public String get(int offset, int length) {
+		String result = null;
+		int myLength = getLength();
+		if (0 > offset)
+			offset = 0;
+		if (0 > length)
+			length = 0;
+		if (offset + length > myLength) {
+			// first try adjusting length to fit
+			int lessLength = myLength - offset;
+			if ((lessLength >= 0) && (offset + lessLength == myLength)) {
+				length = lessLength;
+			}
+			else {
+				// second, try offset
+				int moreOffset = myLength - length;
+				if ((moreOffset >= 0) && (moreOffset + length == myLength)) {
+					offset = moreOffset;
+				}
+				else {
+					// can happen if myLength is 0.
+					// no adjustment possible.
+					result = new String();
+				}
+			}
+
+		}
+		if (result == null) {
+			result = getStore().get(offset, length);
+		}
+		return result;
+	}
+
+	public Object getAdapter(Class adapter) {
+		return Platform.getAdapterManager().getAdapter(this, adapter);
+	}
+
+	IStructuredDocumentRegion getCachedDocumentRegion() {
+		IStructuredDocumentRegion result = null;
+		if (USE_LOCAL_THREAD) {
+			result = fCurrentDocumentRegionCache.get();
+		}
+		else {
+			result = cachedDocumentRegion;
+		}
+		return result;
+	}
+
+	/**
+	 * @see IDocument#getChar
+	 * @exception BadLocationException
+	 *                If position is not a valid range in the document
+	 */
+	public char getChar(int pos) throws BadLocationException {
+		char result = 0x00;
+		try {
+			result = getStore().get(pos);
+		}
+		catch (IndexOutOfBoundsException e) {
+			throw new BadLocationException(e.getLocalizedMessage());
+		}
+		return result;
+	}
+
+	/**
+	 * Returns the type of the document partition containing the given
+	 * character position.
+	 */
+	public String getContentType(int offset) throws BadLocationException {
+		return getDocumentPartitioner().getContentType(offset);
+	}
+
+
+	public String getContentType(String partitioning, int offset, boolean preferOpenPartitions) throws BadLocationException, BadPartitioningException {
+		if ((0 > offset) || (offset > getLength()))
+			throw new BadLocationException();
+
+		IDocumentPartitioner partitioner = getDocumentPartitioner(partitioning);
+
+		if (partitioner instanceof IDocumentPartitionerExtension2)
+			return ((IDocumentPartitionerExtension2) partitioner).getContentType(offset, preferOpenPartitions);
+		else if (partitioner != null)
+			return partitioner.getContentType(offset);
+		else if (IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING.equals(partitioning))
+			return DEFAULT_CONTENT_TYPE;
+		else
+			throw new BadPartitioningException();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension4#getDefaultLineDelimiter()
+	 */
+	public String getDefaultLineDelimiter() {
+		
+		String lineDelimiter= null;
+		
+		try {
+			lineDelimiter= getLineDelimiter(0);
+		} catch (BadLocationException x) {
+		}
+	
+		if (lineDelimiter != null)
+			return lineDelimiter;
+
+		if (fInitialLineDelimiter != null)
+			return fInitialLineDelimiter;
+
+		String sysLineDelimiter= System.getProperty("line.separator"); //$NON-NLS-1$
+		String[] delimiters= getLegalLineDelimiters();
+		Assert.isTrue(delimiters.length > 0);
+		for (int i= 0; i < delimiters.length; i++) {
+			if (delimiters[i].equals(sysLineDelimiter)) {
+				lineDelimiter= sysLineDelimiter;
+				break;
+			}
+		}
+		
+		if (lineDelimiter == null)
+			lineDelimiter= delimiters[0];
+	
+		return lineDelimiter;
+		
+	}
+
+	/**
+	 * Returns the document's partitioner.
+	 * 
+	 * @see IDocumentPartitioner
+	 */
+	public IDocumentPartitioner getDocumentPartitioner() {
+		return getDocumentPartitioner(IDocumentExtension3.DEFAULT_PARTITIONING);
+	}
+
+
+	public IDocumentPartitioner getDocumentPartitioner(String partitioning) {
+
+		IDocumentPartitioner documentPartitioner = null;
+		if (fDocumentPartitioners != null) {
+			documentPartitioner = (IDocumentPartitioner) fDocumentPartitioners.get(partitioning);
+		}
+		return documentPartitioner;
+	}
+
+	public EncodingMemento getEncodingMemento() {
+		return encodingMemento;
+	}
+
+	public IStructuredDocumentRegion getFirstStructuredDocumentRegion() {
+		// should we update cachedNode?
+		// We should to keep consistent philosophy of remembering last
+		// requested position,
+		// for efficiency.
+		setCachedDocumentRegion(firstDocumentRegion);
+		return firstDocumentRegion;
+	}
+
+	public IStructuredDocumentRegion getLastStructuredDocumentRegion() {
+		// should we update cachedNode?
+		// We should to keep consistent philosophy of remembering last
+		// requested position,
+		// for efficiency.
+		setCachedDocumentRegion(lastDocumentRegion);
+		return lastDocumentRegion;
+	}
+
+	/*
+	 * -------------------------- partitions
+	 * ----------------------------------
+	 */
+	public String[] getLegalContentTypes() {
+		String[] result = null;
+		try {
+			result = getLegalContentTypes(IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING);
+		}
+		catch (BadPartitioningException e) {
+			// impossible in this context
+			throw new Error(e);
+		}
+		return result;
+	}
+
+	public String[] getLegalContentTypes(String partitioning) throws BadPartitioningException {
+		IDocumentPartitioner partitioner = getDocumentPartitioner(partitioning);
+		if (partitioner != null)
+			return partitioner.getLegalContentTypes();
+		if (IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING.equals(partitioning))
+			return new String[]{DEFAULT_CONTENT_TYPE};
+		throw new BadPartitioningException();
+	}
+
+	/*
+	 * ------------------ line delimiter conversion
+	 * ---------------------------
+	 */
+	public String[] getLegalLineDelimiters() {
+		return getTracker().getLegalLineDelimiters();
+	}
+
+	/**
+	 * @see IDocument#getLength
+	 */
+	public int getLength() {
+		return getStore().getLength();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument#getLineDelimiter()
+	 */
+	public String getLineDelimiter() {
+		return getDefaultLineDelimiter();
+	}
+
+	/**
+	 * Returns the line delimiter of that line
+	 * 
+	 * @exception BadLocationException
+	 *                If the line number is invalid in the document
+	 */
+	public String getLineDelimiter(int line) throws org.eclipse.jface.text.BadLocationException {
+		return getTracker().getLineDelimiter(line);
+	}
+
+	/**
+	 * Returns a description of the specified line. The line is described by
+	 * its offset and its length excluding the line's delimiter.
+	 * 
+	 * @param line
+	 *            the line of interest
+	 * @return a line description
+	 * @exception BadLocationException
+	 *                if the line number is invalid in this document
+	 */
+	public org.eclipse.jface.text.IRegion getLineInformation(int line) throws org.eclipse.jface.text.BadLocationException {
+		return getTracker().getLineInformation(line);
+	}
+
+	/**
+	 * Returns a description of the line at the given offset. The description
+	 * contains the offset and the length of the line excluding the line's
+	 * delimiter.
+	 * 
+	 * @param offset
+	 *            the offset whose line should be described
+	 * @return a region describing the line
+	 * @exception BadLocationException
+	 *                if offset is invalid in this document
+	 */
+	public org.eclipse.jface.text.IRegion getLineInformationOfOffset(int offset) throws org.eclipse.jface.text.BadLocationException {
+		return getTracker().getLineInformationOfOffset(offset);
+	}
+
+	/*
+	 * ---------------------- line information
+	 * --------------------------------
+	 */
+	public int getLineLength(int line) throws org.eclipse.jface.text.BadLocationException {
+		return getTracker().getLineLength(line);
+	}
+
+	/**
+	 * Determines the offset of the first character of the given line.
+	 * 
+	 * @param line
+	 *            the line of interest
+	 * @return the document offset
+	 * @exception BadLocationException
+	 *                if the line number is invalid in this document
+	 */
+	public int getLineOffset(int line) throws org.eclipse.jface.text.BadLocationException {
+		return getTracker().getLineOffset(line);
+	}
+
+	public int getLineOfOffset(int offset) {
+		int result = -1;
+		try {
+			result = getTracker().getLineNumberOfOffset(offset);
+		}
+		catch (BadLocationException e) {
+			if (Logger.DEBUG_DOCUMENT)
+				Logger.log(Logger.INFO, "Dev. Program Info Only: IStructuredDocument::getLineOfOffset: offset out of range, zero assumed. offset = " + offset, e); //$NON-NLS-1$ //$NON-NLS-2$
+			result = 0;
+		}
+		return result;
+	}
+
+	/**
+	 * Returns the number of lines in this document
+	 * 
+	 * @return the number of lines in this document
+	 */
+	public int getNumberOfLines() {
+		return getTracker().getNumberOfLines();
+	}
+
+	/**
+	 * Returns the number of lines which are occupied by a given text range.
+	 * 
+	 * @param offset
+	 *            the offset of the specified text range
+	 * @param length
+	 *            the length of the specified text range
+	 * @return the number of lines occupied by the specified range
+	 * @exception BadLocationException
+	 *                if specified range is invalid in this tracker
+	 */
+	public int getNumberOfLines(int offset, int length) throws org.eclipse.jface.text.BadLocationException {
+		return getTracker().getNumberOfLines(offset, length);
+	}
+
+	/**
+	 * This is public, temporarily, for use by tag lib classes.
+	 */
+	public RegionParser getParser() {
+		if (fParser == null) {
+			throw new IllegalStateException("IStructuredDocument::getParser. Parser needs to be set before use"); //$NON-NLS-1$
+		}
+		return fParser;
+	}
+
+	/**
+	 * Returns the document partition in which the position is located. The
+	 * partition is specified as typed region.
+	 */
+	public ITypedRegion getPartition(int offset) throws BadLocationException {
+		ITypedRegion partition = null;
+		try {
+			partition = getPartition(IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING, offset, false);
+		}
+		catch (BadPartitioningException e) {
+			throw new Error(e);
+		}
+		if (partition == null) {
+			throw new Error();
+		}
+		return partition;
+	}
+
+
+	public ITypedRegion getPartition(String partitioning, int offset, boolean preferOpenPartitions) throws BadLocationException, BadPartitioningException {
+		if ((0 > offset) || (offset > getLength()))
+			throw new BadLocationException();
+		ITypedRegion result = null;
+
+		IDocumentPartitioner partitioner = getDocumentPartitioner(partitioning);
+
+		if (partitioner instanceof IDocumentPartitionerExtension2) {
+			result = ((IDocumentPartitionerExtension2) partitioner).getPartition(offset, preferOpenPartitions);
+		}
+		else if (partitioner != null) {
+			result = partitioner.getPartition(offset);
+		}
+		else if (IStructuredPartitioning.DEFAULT_STRUCTURED_PARTITIONING.equals(partitioning)) {
+			result = new TypedRegion(0, getLength(), DEFAULT_CONTENT_TYPE);
+		}
+		else
+			throw new BadPartitioningException();
+		return result;
+	}
+
+
+	public String[] getPartitionings() {
+		if (fDocumentPartitioners == null)
+			return new String[0];
+		String[] partitionings = new String[fDocumentPartitioners.size()];
+		fDocumentPartitioners.keySet().toArray(partitionings);
+		return partitionings;
+	}
+
+	/**
+	 * Returns all position categories added to this document.
+	 */
+	public String[] getPositionCategories() {
+		return getPositionManager().getPositionCategories();
+	}
+
+	/**
+	 * @return Returns the positionManager.
+	 */
+	private GenericPositionManager getPositionManager() {
+		if (fPositionManager == null) {
+			fPositionManager = new GenericPositionManager(this);
+		}
+		return fPositionManager;
+	}
+
+	/**
+	 * Returns all Positions of the given position category.
+	 * 
+	 * @exception BadPositionCategoryException
+	 *                If category is not defined for the document
+	 */
+	public Position[] getPositions(String category) throws org.eclipse.jface.text.BadPositionCategoryException {
+		return getPositionManager().getPositions(category);
+	}
+
+	/**
+	 * @see IDocument#getPositionUpdaters
+	 */
+	public IPositionUpdater[] getPositionUpdaters() {
+		return getPositionManager().getPositionUpdaters();
+	}
+
+	/**
+	 * This method can return null, which is the case if the offset is just
+	 * before or just after the existing text. Compare with
+	 * getNodeAtCharacterOffset.
+	 */
+	public IStructuredDocumentRegion getRegionAtCharacterOffset(int offset) {
+		IStructuredDocumentRegion result = null;
+
+		// FIXME: need to synch on 'cachedRegion' (but since that's a
+		// constantly changing object, we
+		// can't, so need to add a "region_lock" object, and use it here, and
+		// in re-parser.
+		// Oh, and need to make sure, after synch, that the region is not
+		// deleted, and if so, I guess go back
+		// to the beginning!
+
+		// cached node can be null when document is empty
+		IStructuredDocumentRegion potentialCachedRegion = getCachedDocumentRegion();
+		if (potentialCachedRegion != null) {
+
+			// 
+
+			// if we already have the right node, return that.
+			if (potentialCachedRegion.containsOffset(offset)) {
+				result = potentialCachedRegion;
+			}
+			else {
+				// first, find out what direction to go, relative to
+				// cachedNode.
+				// negative means "towards the front" of the file,
+				// postitive
+				// means
+				// towards the end.
+				int direction = offset - potentialCachedRegion.getStart();
+				if (direction < 0) {
+					// search towards beginning
+					while (!potentialCachedRegion.containsOffset(offset)) {
+						IStructuredDocumentRegion tempNode = potentialCachedRegion.getPrevious();
+						if (tempNode == null) {
+							break;
+						}
+						else {
+							potentialCachedRegion = tempNode;
+						}
+					}
+				}
+				else {
+					// search towards end
+					// There is a legitamat condition where the
+					// offset will not be contained in any node,
+					// which is if the offset is just past the last
+					// character of text.
+					// And, we must gaurd against setting cachedNode to
+					// null!
+					while (!potentialCachedRegion.containsOffset(offset)) {
+						IStructuredDocumentRegion tempNode = potentialCachedRegion.getNext();
+						if (tempNode == null)
+							break;
+						else
+							potentialCachedRegion = tempNode;
+					}
+				}
+			}
+			result = potentialCachedRegion;
+		}
+		// just to be doubly sure we never assign null to an already valid
+		// cachedRegion.
+		// I believe any time 'result' is null at this point, that just means
+		// we have an
+		// empty document, and the cachedRegion is already null, but we check
+		// and print
+		// warning, just so during development we be sure we never accidently
+		// break this assumption.
+		if (result != null)
+			setCachedDocumentRegion(result);
+		else if (getCachedDocumentRegion() != null) {
+			throw new IllegalStateException("Program Error: no region could be found to cache, but cache was non null. Indicates corrupted model or region list"); //$NON-NLS-1$
+		}
+
+		return result;
+	}
+
+	public IStructuredDocumentRegionList getRegionList() {
+		CoreNodeList result = null;
+		if (getCachedDocumentRegion() == null)
+			result = new CoreNodeList(null);
+		else
+			result = new CoreNodeList(getFirstStructuredDocumentRegion());
+
+		return result;
+	}
+
+
+	public IStructuredDocumentRegion[] getStructuredDocumentRegions() {
+		return getStructuredDocumentRegions(0, getLength());
+	}
+
+	/**
+	 * <p>
+	 * In the case of 0 length, the <code>IStructuredDocumentRegion</code>
+	 * at the character offset is returened. In other words, the region to the
+	 * right of the caret is returned. except for at the end of the document,
+	 * then the last region is returned.
+	 * </p>
+	 * <p>
+	 * Otherwise all the regions "inbetween" the indicated range are returned,
+	 * including the regions which overlap the region.
+	 * </p>
+	 * 
+	 * <br>
+	 * eg.
+	 * <p>
+	 * <br>
+	 * eg.
+	 * 
+	 * <pre>
+	 *                        &lt;html&gt;[&lt;head&gt;&lt;/head&gt;]&lt;/html&gt; returns &lt;head&gt;,&lt;/head&gt;
+	 * </pre>
+	 *    <pre>
+	 *                        &lt;ht[ml&gt;&lt;head&gt;&lt;/he]ad&gt;&lt;/html&gt; returns &lt;html&gt;,&lt;head&gt;,&lt;/head&gt;
+	 * </pre>
+	 * 
+	 * <pre>
+	 *                          &lt;html&gt;[&lt;head&gt;&lt;/head&gt;]&lt;/html&gt; returns &lt;head&gt;,&lt;/head&gt;
+	 * </pre>
+	 *    <pre>
+	 *                          &lt;ht[ml&gt;&lt;head&gt;&lt;/he]ad&gt;&lt;/html&gt; returns &lt;html&gt;,&lt;head&gt;,&lt;/head&gt;
+	 * </pre>
+	 * 
+	 * </p>
+	 */
+	public IStructuredDocumentRegion[] getStructuredDocumentRegions(int start, int length) {
+
+		if (length < 0)
+			throw new IllegalArgumentException("can't have negative length"); //$NON-NLS-1$
+
+		// this will make the right edge of the range point into the selection
+		// eg. <html>[<head></head>]</html>
+		// will return <head>,</head> instead of <head>,</head>,</html>
+		if (length > 0)
+			length--;
+
+		List results = new ArrayList();
+
+		// start thread safe block
+		try {
+			acquireLock();
+
+			IStructuredDocumentRegion currentRegion = getRegionAtCharacterOffset(start);
+			IStructuredDocumentRegion endRegion = getRegionAtCharacterOffset(start + length);
+			while (currentRegion != endRegion && currentRegion != null) {
+				results.add(currentRegion);
+				currentRegion = currentRegion.getNext();
+			}
+			// need to add that last end region
+			// can be null in the case of an empty document
+			if (endRegion != null)
+				results.add(endRegion);
+		}
+		finally {
+			releaseLock();
+		}
+		// end thread safe block
+
+		return (IStructuredDocumentRegion[]) results.toArray(new IStructuredDocumentRegion[results.size()]);
+	}
+
+	/**
+	 * was made public for easier testing. Normally should never be used by
+	 * client codes.
+	 */
+	public IStructuredTextReParser getReParser() {
+		if (fReParser == null) {
+			fReParser = new StructuredDocumentReParser();
+			fReParser.setStructuredDocument(this);
+		}
+		return fReParser;
+	}
+
+	private ITextStore getStore() {
+		return fStore;
+	}
+
+	public String getText() {
+		String result = get();
+		return result;
+	}
+
+	/**
+	 * Returns the document's line tracker. Assumes that the document has been
+	 * initialized with a line tracker.
+	 * 
+	 * @return the document's line tracker
+	 */
+	private ILineTracker getTracker() {
+		return fTracker;
+	}
+
+	public IStructuredTextUndoManager getUndoManager() {
+		if (fUndoManager == null) {
+			fUndoManager = new StructuredTextUndoManager();
+		}
+		return fUndoManager;
+	}
+
+	void initializeFirstAndLastDocumentRegion() {
+		// cached Node must also be first, at the initial point. Only
+		// valid
+		// to call this method right after the first parse.
+		// 
+		// when starting afresh, our cachedNode should be our firstNode,
+		// so be sure to initialize the firstNode
+		firstDocumentRegion = getCachedDocumentRegion();
+		// be sure to use 'getNext' for this initial finding of the last
+		// node,
+		// since the implementation of node.getLastNode may simply call
+		// structuredDocument.getLastStructuredDocumentRegion!
+		IStructuredDocumentRegion aNode = firstDocumentRegion;
+		if (aNode == null) {
+			// defect 254607: to handle empty documents right, if
+			// firstnode is
+			// null, make sure last node is null too
+			lastDocumentRegion = null;
+		}
+		else {
+			while (aNode != null) {
+				lastDocumentRegion = aNode;
+				aNode = aNode.getNext();
+			}
+		}
+	}
+
+	/**
+	 * @see IDocument#insertPositionUpdater
+	 */
+	public void insertPositionUpdater(IPositionUpdater updater, int index) {
+		getPositionManager().insertPositionUpdater(updater, index);
+	}
+
+	private void internal_addPositionCategory(String category) {
+		getPositionManager().addPositionCategory(category);
+	}
+
+	private void internal_addPositionUpdater(IPositionUpdater updater) {
+		getPositionManager().addPositionUpdater(updater);
+	}
+
+	private void internal_setParser(RegionParser newParser) {
+		fParser = newParser;
+	}
+
+	String internalGet(int offset, int length) {
+		String result = null;
+		// int myLength = getLength();
+		// if ((0 > offset) || (0 > length) || (offset + length > myLength))
+		// throw new BadLocationException();
+		result = getStore().get(offset, length);
+		return result;
+	}
+
+	/**
+	 * @param requester
+	 * @param start
+	 * @param replacementLength
+	 * @param changes
+	 * @param modificationStamp
+	 * @param ignoreReadOnlySettings
+	 * @return
+	 */
+	private StructuredDocumentEvent internalReplaceText(Object requester, int start, int replacementLength, String changes, long modificationStamp, boolean ignoreReadOnlySettings) {
+		StructuredDocumentEvent result = null;
+
+		stopPostNotificationProcessing();
+		if (changes == null)
+			changes = ""; //$NON-NLS-1$
+		// 
+		if (Debug.debugStructuredDocument)
+			System.out.println(getClass().getName() + "::replaceText(" + start + "," + replacementLength + "," + changes + ")"); //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+		if (Debug.perfTestStructuredDocumentOnly || Debug.perfTest || Debug.perfTestRawStructuredDocumentOnly) {
+			startStreamTime = System.currentTimeMillis();
+		}
+		try {
+			// Note: event must be computed before 'fire' method called
+			fDocumentEvent = new DocumentEvent(this, start, replacementLength, changes);
+			fireDocumentAboutToChanged();
+
+			try {
+				acquireLock();
+
+				if (!ignoreReadOnlySettings && (containsReadOnly(start, replacementLength))) {
+					NoChangeEvent noChangeEvent = new NoChangeEvent(this, requester, changes, start, replacementLength);
+					noChangeEvent.reason = NoChangeEvent.READ_ONLY_STATE_CHANGE;
+					result = noChangeEvent;
+				}
+				else {
+					result = updateModel(requester, start, replacementLength, changes);
+				}
+			}
+			finally {
+				releaseLock();
+			}
+
+
+			if (Debug.perfTestRawStructuredDocumentOnly || Debug.perfTest) {
+				long stopStreamTime = System.currentTimeMillis();
+				System.out.println("\n\t\t\t\t Time for IStructuredDocument raw replaceText: " + (stopStreamTime - startStreamTime)); //$NON-NLS-1$
+			}
+			if (Debug.debugStructuredDocument) {
+				System.out.println("event type returned by replaceTextWithNoDebuggingThread: " + result); //$NON-NLS-1$
+			}
+		}
+		finally {
+			// FUTURE_TO_DO: implement callback mechanism? to avoid instanceof
+			// and casting
+			// fireStructuredDocumentEvent must be called in order to end
+			// documentAboutToBeChanged state
+
+
+			// increment modification stamp if modifications were made
+			if (result != null && !(result instanceof NoChangeEvent)) {
+				fModificationStamp= modificationStamp;
+				fNextModificationStamp= Math.max(fModificationStamp, fNextModificationStamp);
+				fDocumentEvent.fModificationStamp = fModificationStamp;
+			}
+				
+			if (result == null) {
+				// result should not be null, but if an exception was thrown,
+				// it will be
+				// so send a noChangeEvent and log the problem
+				NoChangeEvent noChangeEvent = new NoChangeEvent(this, requester, changes, start, replacementLength);
+				noChangeEvent.reason = NoChangeEvent.NO_EVENT;
+				fireStructuredDocumentEvent(noChangeEvent);
+				Logger.log(Logger.ERROR, "Program Error: invalid structured document event"); //$NON-NLS-1$
+			}
+			else {
+				if (result instanceof RegionChangedEvent) {
+					fireStructuredDocumentEvent((RegionChangedEvent) result);
+				}
+				else {
+					if (result instanceof RegionsReplacedEvent) {
+						fireStructuredDocumentEvent((RegionsReplacedEvent) result);
+					}
+					else {
+						if (result instanceof StructuredDocumentRegionsReplacedEvent) {
+							// probably more efficient to mark old regions as
+							// 'deleted' at the time
+							// that are determined to be deleted, but I'll do
+							// here
+							// in then central spot
+							// for programming ease.
+							updateDeletedFields((StructuredDocumentRegionsReplacedEvent) result);
+							fireStructuredDocumentEvent((StructuredDocumentRegionsReplacedEvent) result);
+						}
+						else {
+							if (result instanceof NoChangeEvent) {
+								fireStructuredDocumentEvent((NoChangeEvent) result);
+							}
+							else {
+								// if here, this means a new event was created
+								// and not handled here
+								// just send a no event until this issue is
+								// resolved.
+								NoChangeEvent noChangeEvent = new NoChangeEvent(this, requester, changes, start, replacementLength);
+								noChangeEvent.reason = NoChangeEvent.NO_EVENT;
+								fireStructuredDocumentEvent(noChangeEvent);
+								Logger.log(Logger.INFO, "Program Error: unexpected structured document event: " + result); //$NON-NLS-1$
+							}
+						}
+					}
+				}
+			}
+
+			if (Debug.perfTest || Debug.perfTestStructuredDocumentOnly) {
+				long stopStreamTime = System.currentTimeMillis();
+				System.out.println("\n\t\t\t\t Total Time for IStructuredDocument event signaling/processing in replaceText: " + (stopStreamTime - startStreamTime)); //$NON-NLS-1$
+			}
+			resumePostNotificationProcessing();
+		}
+		return result;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.CharSequence#length()
+	 */
+	public int length() {
+
+		return getLength();
+	}
+	
+	public void makeReadOnly(int startOffset, int length) {
+		makeReadOnly(startOffset, length, false, false);
+	}
+
+	public void makeReadOnly(int startOffset, int length, boolean canInsertBefore, boolean canInsertAfter) {	
+		// doesn't make sense to have a readonly region of 0 length,
+		// so we'll ignore those requests
+		if (length <= 0)
+			return;
+		String affectedText = this.get(startOffset, length);
+		// a document event for "read only" change ... must
+		// be followed by "no change" structuredDocument event
+		// fDocumentEvent = new DocumentEvent(this, startOffset, length,
+		// affectedText);
+		fireReadOnlyAboutToBeChanged();
+		// if (containsReadOnly(startOffset, length)) {
+		// adjustReadOnlyRegions(startOffset, length);
+		// } else {
+		// we can blindly add category, since no harm done if already
+		// exists.
+		addPositionCategory(READ_ONLY_REGIONS_CATEGORY);
+		Position newPosition = new ReadOnlyPosition(startOffset, length, canInsertBefore);
+		try {
+			addPosition(READ_ONLY_REGIONS_CATEGORY, newPosition);
+			// FIXME: need to change API to pass in requester, so this event
+			// can be
+			// created correctly, instead of using null.
+			NoChangeEvent noChangeEvent = new NoChangeEvent(this, null, affectedText, startOffset, length);
+			noChangeEvent.reason = NoChangeEvent.READ_ONLY_STATE_CHANGE;
+			fireReadOnlyStructuredDocumentEvent(noChangeEvent);
+		}
+		catch (BadLocationException e) {
+			// for now, log and ignore. Perhaps later we
+			// could adjust to handle some cases?
+			Logger.logException(("could not create readonly region at " + startOffset + " to " + length), e); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		catch (BadPositionCategoryException e) {
+			// should never occur, since we add category
+			Logger.logException(e);
+		}
+	}
+
+	public IStructuredDocument newInstance() {
+		IStructuredDocument newInstance = StructuredDocumentFactory.getNewStructuredDocumentInstance(getParser().newInstance());
+		((BasicStructuredDocument) newInstance).setReParser(getReParser().newInstance());
+		if (getDocumentPartitioner() instanceof StructuredTextPartitioner) {
+			newInstance.setDocumentPartitioner(((StructuredTextPartitioner) getDocumentPartitioner()).newInstance());
+			newInstance.getDocumentPartitioner().connect(newInstance);
+		}
+		newInstance.setLineDelimiter(getLineDelimiter());
+		if (getEncodingMemento() != null) {
+			newInstance.setEncodingMemento((EncodingMemento) getEncodingMemento().clone());
+		}
+		return newInstance;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.internal.text.IRegionComparible#regionMatches(int,
+	 *      int, java.lang.String)
+	 */
+	public boolean regionMatches(int offset, int length, String stringToCompare) {
+		boolean result = false;
+		ITextStore store = getStore();
+		if (store instanceof IRegionComparible) {
+			result = ((IRegionComparible) store).regionMatches(offset, length, stringToCompare);
+		}
+		else {
+			result = get(offset, length).equals(stringToCompare);
+		}
+		return result;
+	}
+
+	public boolean regionMatchesIgnoreCase(int offset, int length, String stringToCompare) {
+		boolean result = false;
+		ITextStore store = getStore();
+		if (store instanceof IRegionComparible) {
+			result = ((IRegionComparible) store).regionMatchesIgnoreCase(offset, length, stringToCompare);
+		}
+		else {
+			result = get(offset, length).equalsIgnoreCase(stringToCompare);
+		}
+		return result;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension#registerPostNotificationReplace(org.eclipse.jface.text.IDocumentListener,
+	 *      org.eclipse.jface.text.IDocumentExtension.IReplace)
+	 */
+	public void registerPostNotificationReplace(IDocumentListener owner, IDocumentExtension.IReplace replace) {
+		if (fAcceptPostNotificationReplaces) {
+			if (fPostNotificationChanges == null)
+				fPostNotificationChanges = new ArrayList(1);
+			fPostNotificationChanges.add(new RegisteredReplace(owner, replace));
+		}
+	}
+
+	protected void releaseLock() {
+		// do nothing here in super class
+	}
+
+	public void removeDocumentAboutToChangeListener(IModelAboutToBeChangedListener listener) {
+		synchronized (listenerLock) {
+
+			if ((fStructuredDocumentAboutToChangeListeners != null) && (listener != null)) {
+				// if its not in the listeners, we'll ignore the request
+				if (Utilities.contains(fStructuredDocumentAboutToChangeListeners, listener)) {
+					int oldSize = fStructuredDocumentAboutToChangeListeners.length;
+					int newSize = oldSize - 1;
+					Object[] newListeners = new Object[newSize];
+					int index = 0;
+					for (int i = 0; i < oldSize; i++) {
+						if (fStructuredDocumentAboutToChangeListeners[i] == listener) { // ignore
+						}
+						else {
+							// copy old to new if its not the one we are
+							// removing
+							newListeners[index++] = fStructuredDocumentAboutToChangeListeners[i];
+						}
+					}
+					// now that we have a new array, let's switch it for the
+					// old
+					// one
+					fStructuredDocumentAboutToChangeListeners = newListeners;
+				}
+			}
+		}
+	}
+
+	/**
+	 * removeModelChangedListener method comment.
+	 */
+	public void removeDocumentChangedListener(IStructuredDocumentListener listener) {
+		synchronized (listenerLock) {
+
+			if ((fStructuredDocumentChangedListeners != null) && (listener != null)) {
+				// if its not in the listeners, we'll ignore the request
+				if (Utilities.contains(fStructuredDocumentChangedListeners, listener)) {
+					int oldSize = fStructuredDocumentChangedListeners.length;
+					int newSize = oldSize - 1;
+					Object[] newListeners = new Object[newSize];
+					int index = 0;
+					for (int i = 0; i < oldSize; i++) {
+						if (fStructuredDocumentChangedListeners[i] == listener) { // ignore
+						}
+						else {
+							// copy old to new if its not the one we are
+							// removing
+							newListeners[index++] = fStructuredDocumentChangedListeners[i];
+						}
+					}
+					// now that we have a new array, let's switch it for the
+					// old
+					// one
+					fStructuredDocumentChangedListeners = newListeners;
+				}
+			}
+		}
+	}
+
+	public void removeDocumentChangingListener(IStructuredDocumentListener listener) {
+		synchronized (listenerLock) {
+
+			if ((fStructuredDocumentChangingListeners != null) && (listener != null)) {
+				// if its not in the listeners, we'll ignore the request
+				if (Utilities.contains(fStructuredDocumentChangingListeners, listener)) {
+					int oldSize = fStructuredDocumentChangingListeners.length;
+					int newSize = oldSize - 1;
+					Object[] newListeners = new Object[newSize];
+					int index = 0;
+					for (int i = 0; i < oldSize; i++) {
+						if (fStructuredDocumentChangingListeners[i] == listener) { // ignore
+						}
+						else {
+							// copy old to new if its not the one we are
+							// removing
+							newListeners[index++] = fStructuredDocumentChangingListeners[i];
+						}
+					}
+					// now that we have a new array, let's switch it for the
+					// old
+					// one
+					fStructuredDocumentChangingListeners = newListeners;
+				}
+			}
+		}
+	}
+
+	public void removeDocumentListener(IDocumentListener listener) {
+		synchronized (listenerLock) {
+
+			if ((fDocumentListeners != null) && (listener != null)) {
+				// if its not in the listeners, we'll ignore the request
+				if (Utilities.contains(fDocumentListeners, listener)) {
+					int oldSize = fDocumentListeners.length;
+					int newSize = oldSize - 1;
+					IDocumentListener[] newListeners = new IDocumentListener[newSize];
+					int index = 0;
+					for (int i = 0; i < oldSize; i++) {
+						if (fDocumentListeners[i] == listener) { // ignore
+						}
+						else {
+							// copy old to new if its not the one we are
+							// removing
+							newListeners[index++] = fDocumentListeners[i];
+						}
+					}
+					// now that we have a new array, let's switch it for the
+					// old
+					// one
+					fDocumentListeners = newListeners;
+				}
+			}
+		}
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#removeDocumentPartitioningListener(org.eclipse.jface.text.IDocumentPartitioningListener)
+	 */
+	public void removeDocumentPartitioningListener(IDocumentPartitioningListener listener) {
+		synchronized (listenerLock) {
+
+			Assert.isNotNull(listener);
+			if (fDocumentPartitioningListeners != null)
+				fDocumentPartitioningListeners.remove(listener);
+		}
+	}
+
+	/**
+	 * Removes the given <code>Position</code> from the document's default
+	 * position category. The default position category is to be defined by
+	 * the implementers. If the position is not part of the document's default
+	 * category nothing happens.
+	 */
+	public void removePosition(Position position) {
+		getPositionManager().removePosition(position);
+	}
+
+	/**
+	 * @see IDocument#removePosition
+	 * @exception BadPositionCategoryException
+	 *                If the category is not defined for the document
+	 */
+	public void removePosition(String category, Position position) throws BadPositionCategoryException {
+		getPositionManager().removePosition(category, position);
+	}
+
+	/**
+	 * @see IDocument#removePositionCategory
+	 * @exception BadPositionCategoryException
+	 *                If the category is not defined for the document
+	 */
+	public void removePositionCategory(String category) throws BadPositionCategoryException {
+		getPositionManager().removePositionCategory(category);
+	}
+
+	/**
+	 * @see IDocument#removePositionUpdater
+	 */
+	public void removePositionUpdater(IPositionUpdater updater) {
+		getPositionManager().removePositionUpdater(updater);
+	}
+
+	/**
+	 * Removes the given document listener from teh document's list of
+	 * prenotified document listeners. If the listener is not registered with
+	 * the document nothing happens.
+	 * <p>
+	 * 
+	 * This method is not for public use, it may only be called by
+	 * implementers of <code>IDocumentAdapter</code> and only if those
+	 * implementers need to implement <code>IDocumentListener</code>.
+	 * 
+	 * @param documentAdapter
+	 *            the listener to be removed
+	 * 
+	 * @see #addPrenotifiedDocumentListener(IDocumentListener)
+	 */
+	public void removePrenotifiedDocumentListener(org.eclipse.jface.text.IDocumentListener documentAdapter) {
+		synchronized (listenerLock) {
+
+			if (Utilities.contains(fPrenotifiedDocumentListeners, documentAdapter)) {
+				int previousSize = fPrenotifiedDocumentListeners.length;
+				if (previousSize > 1) {
+					IDocumentListener[] listeners = new IDocumentListener[previousSize - 1];
+					int previousIndex = 0;
+					int newIndex = 0;
+					while (previousIndex < previousSize) {
+						if (fPrenotifiedDocumentListeners[previousIndex] != documentAdapter)
+							listeners[newIndex++] = fPrenotifiedDocumentListeners[previousIndex];
+						previousIndex++;
+					}
+					fPrenotifiedDocumentListeners = listeners;
+				}
+				else {
+					fPrenotifiedDocumentListeners = null;
+				}
+			}
+		}
+	}
+
+	/**
+	 * This method is for INTERNAL USE ONLY and is NOT API.
+	 * 
+	 * Rebuilds the StructuredDocumentRegion chain from the existing text.
+	 * FileBuffer support does not allow clients to know the document's
+	 * location before the text contents are set.
+	 * 
+	 * @see set(String)
+	 */
+	public void reparse(Object requester) {
+		// check if we're already making document-wide changes on this thread
+		if (fStoppedCount > 0)
+			return;
+		
+		stopPostNotificationProcessing();
+		clearReadOnly();
+
+		try {
+			acquireLock();
+
+			CharSequenceReader subSetTextStoreReader = new CharSequenceReader((CharSequence) getStore(), 0, getStore().getLength());
+			resetParser(subSetTextStoreReader, 0);
+			//
+			setCachedDocumentRegion(getParser().getDocumentRegions());
+			// when starting afresh, our cachedNode should be our firstNode,
+			// so be sure to initialize the firstNode and lastNode
+			initializeFirstAndLastDocumentRegion();
+			StructuredDocumentRegionIterator.setParentDocument(getCachedDocumentRegion(), this);
+		}
+		finally {
+			releaseLock();
+		}
+
+		resumePostNotificationProcessing();
+	}
+
+	/**
+	 * @see IDocument#replace
+	 * @exception BadLocationException
+	 *                If position is not a valid range in the document
+	 */
+	public void replace(int offset, int length, String text) throws BadLocationException {
+		if (Debug.displayWarnings) {
+			System.out.println("Note: IStructuredDocument::replace(int, int, String) .... its better to use replaceText(source, string, int, int) API for structuredDocument updates"); //$NON-NLS-1$
+		}
+		replaceText(this, offset, length, text);
+	}
+
+	/**
+	 * Replace the text with "newText" starting at position "start" for a
+	 * length of "replaceLength".
+	 * <p>
+	 * 
+	 * @param pos
+	 *            start offset of text to replace None of the offsets include
+	 *            delimiters of preceeding lines. Offset 0 is the first
+	 *            character of the document.
+	 * @param length
+	 *            start offset of text to replace
+	 * @param text
+	 *            start offset of text to replace
+	 *            <p>
+	 *            Implementors have to notify TextChanged listeners after the
+	 *            content has been updated. The TextChangedEvent should be set
+	 *            as follows:
+	 * 
+	 * event.type = SWT.TextReplaced event.start = start of the replaced text
+	 * event.numReplacedLines = number of replaced lines event.numNewLines =
+	 * number of new lines event.replacedLength = length of the replaced text
+	 * event.newLength = length of the new text
+	 * 
+	 * NOTE: numNewLines is the number of inserted lines and numReplacedLines
+	 * is the number of deleted lines based on the change that occurs
+	 * visually. For example:
+	 * 
+	 * replacedText newText numReplacedLines numNewLines "" "\n" 0 1 "\n\n"
+	 * "a" 2 0 "a" "\n\n" 0 2
+	 */
+	/**
+	 * One of the APIs to manipulate the IStructuredDocument in terms of text.
+	 */
+	public StructuredDocumentEvent replaceText(Object requester, int pos, int length, String text) {
+		if (length == 0 && (text == null || text.length() == 0))
+			return replaceText(requester, pos, length, text, getModificationStamp(), true);
+		else
+			return replaceText(requester, pos, length, text, getNextModificationStamp(), true);
+	}
+
+	public StructuredDocumentEvent replaceText(Object requester, int start, int replacementLength, String changes, boolean ignoreReadOnlySettings) {
+		long modificationStamp;
+		
+		if (replacementLength == 0 && (changes == null || changes.length() == 0))
+			modificationStamp = getModificationStamp();
+		else
+			modificationStamp = getNextModificationStamp();
+		
+		return replaceText(requester, start, replacementLength, changes, modificationStamp, ignoreReadOnlySettings);
+	}
+	
+	private StructuredDocumentEvent replaceText(Object requester, int start, int replacementLength, String changes, long modificationStamp, boolean ignoreReadOnlySettings) {
+		StructuredDocumentEvent event = internalReplaceText(requester, start, replacementLength, changes, modificationStamp, ignoreReadOnlySettings);
+		return event;
+	}
+
+	void resetParser(int startOffset, int endOffset) {
+
+		RegionParser parser = getParser();
+		ITextStore textStore = getStore();
+		if (textStore instanceof CharSequence) {
+			CharSequenceReader subSetTextStoreReader = new CharSequenceReader((CharSequence) textStore, startOffset, endOffset - startOffset);
+			parser.reset(subSetTextStoreReader, startOffset);
+		}
+		else {
+			String newNodeText = get(startOffset, endOffset - startOffset);
+			parser.reset(newNodeText, startOffset);
+
+		}
+
+	}
+
+	void resetParser(Reader reader, int startOffset) {
+		RegionParser parser = getParser();
+		parser.reset(reader, startOffset);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension#resumePostNotificationProcessing()
+	 */
+	public void resumePostNotificationProcessing() {
+		--fStoppedCount;
+		if (fStoppedCount == 0 && fReentranceCount == 0)
+			executePostNotificationChanges();
+	}
+
+	/**
+	 * @deprecated in superclass in 3.0 - use a FindReplaceDocumentAdapter
+	 *             directly
+	 * @see IDocument#search
+	 */
+	public int search(int startPosition, String findString, boolean forwardSearch, boolean caseSensitive, boolean wholeWord) throws BadLocationException {
+		// (dmw) I added this warning, to know if still being used. I'm not
+		// sure it
+		// works as expected any longer.
+		// but the warning should be removed, once know.
+		Logger.log(Logger.INFO, "WARNING: using unsupported deprecated method 'search'"); //$NON-NLS-1$
+		int offset = -1;
+		IRegion match = new FindReplaceDocumentAdapter(this).find(startPosition, findString, forwardSearch, caseSensitive, wholeWord, false);
+		if (match != null) {
+			offset = match.getOffset();
+		}
+		return offset;
+	}
+
+	/**
+	 * @see IDocument#setText
+	 */
+	public void set(String string) {
+		if (Debug.displayInfo) {
+			System.out.println("Note: IStructuredDocument::setText(String) .... its better to use setText(source, string) API for structuredDocument updates"); //$NON-NLS-1$
+		}
+		setText(null, string);
+	}
+
+	/**
+	 * This may be marked public, but should be packaged protected, once
+	 * refactoring is complete (in other words, not for client use).
+	 */
+	public void setCachedDocumentRegion(IStructuredDocumentRegion structuredRegion) {
+		if (USE_LOCAL_THREAD) {
+			fCurrentDocumentRegionCache.set(structuredRegion);
+		}
+		else {
+			cachedDocumentRegion = structuredRegion;
+		}
+	}
+
+	/**
+	 * Sets the document's partitioner.
+	 * 
+	 * @see IDocumentPartitioner
+	 */
+	public void setDocumentPartitioner(IDocumentPartitioner partitioner) {
+		setDocumentPartitioner(IDocumentExtension3.DEFAULT_PARTITIONING, partitioner);
+	}
+
+
+	public void setDocumentPartitioner(String partitioning, IDocumentPartitioner partitioner) {
+		if (partitioner == null) {
+			if (fDocumentPartitioners != null) {
+				fDocumentPartitioners.remove(partitioning);
+				if (fDocumentPartitioners.size() == 0)
+					fDocumentPartitioners = null;
+			}
+		}
+		else {
+			if (fDocumentPartitioners == null)
+				fDocumentPartitioners = new HashMap();
+			fDocumentPartitioners.put(partitioning, partitioner);
+		}
+		DocumentPartitioningChangedEvent event = new DocumentPartitioningChangedEvent(this);
+		event.setPartitionChange(partitioning, 0, getLength());
+		fireDocumentPartitioningChanged(event);
+	}
+
+	public void setEncodingMemento(EncodingMemento encodingMemento) {
+		this.encodingMemento = encodingMemento;
+	}
+
+	void setFirstDocumentRegion(IStructuredDocumentRegion region) {
+		firstDocumentRegion = region;
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension4#setInitialLineDelimiter(java.lang.String)
+	 */
+	public void setInitialLineDelimiter(String lineDelimiter) {
+		// make sure our preferred delimiter is
+		// one of the legal ones
+		if (Utilities.containsString(getLegalLineDelimiters(), lineDelimiter)) {
+			fInitialLineDelimiter= lineDelimiter;
+		}
+		else {
+			if (Logger.DEBUG_DOCUMENT)
+				Logger.log(Logger.INFO, "Attempt to set linedelimiter to non-legal delimiter"); //$NON-NLS-1$ //$NON-NLS-2$
+			fInitialLineDelimiter = Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, System.getProperty("line.separator"), new IScopeContext[] { new InstanceScope() });//$NON-NLS-1$
+		}
+	}
+
+	void setLastDocumentRegion(IStructuredDocumentRegion region) {
+		lastDocumentRegion = region;
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument#setLineDelimiter(java.lang.String)
+	 */
+	public void setLineDelimiter(String delimiter) {
+		setInitialLineDelimiter(delimiter);
+	}
+
+	/**
+	 * Sets the document's line tracker. Must be called at the beginning of
+	 * the constructor.
+	 * 
+	 * @param tracker
+	 *            the document's line tracker
+	 */
+	private void setLineTracker(ILineTracker tracker) {
+		Assert.isNotNull(tracker);
+		fTracker = tracker;
+	}
+
+	public void setParser(RegionParser newParser) {
+		internal_setParser(newParser);
+	}
+
+	/**
+	 * @param positionManager
+	 *            The positionManager to set.
+	 */
+	// TODO: make private is needed, else remove
+	void setPositionManager(GenericPositionManager positionManager) {
+		fPositionManager = positionManager;
+	}
+
+	/**
+	 * 
+	 */
+	public void setReParser(IStructuredTextReParser newReParser) {
+		fReParser = newReParser;
+		if (fReParser != null) {
+			fReParser.setStructuredDocument(this);
+		}
+	}
+
+	/**
+	 * One of the APIs to manipulate the IStructuredDocument in terms of text.
+	 */
+	public StructuredDocumentEvent setText(Object requester, String theString) {
+		StructuredDocumentEvent result = null;
+		result = replaceText(requester, 0, getLength(), theString, getNextModificationStamp(), true);
+		return result;
+	}
+
+	/**
+	 * Sets the document's text store. Must be called at the beginning of the
+	 * constructor.
+	 * 
+	 * @param store
+	 *            the document's text store
+	 */
+	private void setTextStore(ITextStore store) {
+		Assert.isNotNull(store);
+		fStore = store;
+	}
+
+	public void setUndoManager(IStructuredTextUndoManager undoManager) {
+
+		// if the undo manager has already been set, then
+		// fail fast, since changing the undo manager will lead
+		// to unusual results (or at least loss of undo stack).
+		if (fUndoManager != null && fUndoManager != undoManager) {
+			throw new IllegalArgumentException("can not change undo manager once its been set"); //$NON-NLS-1$
+		}
+		else {
+			fUndoManager = undoManager;
+		}
+	}
+
+
+	/*
+	 * {@inheritDoc}
+	 */
+	public void startSequentialRewrite(boolean normalized) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension#stopPostNotificationProcessing()
+	 */
+	public void stopPostNotificationProcessing() {
+		++fStoppedCount;
+	}
+
+
+	/*
+	 * {@inheritDoc}
+	 */
+	public void stopSequentialRewrite() {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.CharSequence#subSequence(int, int)
+	 */
+	public CharSequence subSequence(int arg0, int arg1) {
+		return get(arg0, arg1);
+	}
+
+	/**
+	 * @param result
+	 */
+	private void updateDeletedFields(StructuredDocumentRegionsReplacedEvent event) {
+		IStructuredDocumentRegionList oldRegions = event.getOldStructuredDocumentRegions();
+		for (int i = 0; i < oldRegions.getLength(); i++) {
+			IStructuredDocumentRegion structuredDocumentRegion = oldRegions.item(i);
+			structuredDocumentRegion.setDeleted(true);
+		}
+
+	}
+
+	/**
+	 * Called by re-parser. Note: this method may be "public" but should only
+	 * be called by re-parsers in the right circumstances.
+	 */
+	public void updateDocumentData(int start, int lengthToReplace, String changes) {
+		stopPostNotificationProcessing();
+		getStore().replace(start, lengthToReplace, changes);
+		try {
+			getTracker().replace(start, lengthToReplace, changes);
+		}
+
+		catch (BadLocationException e) {
+			// should be impossible here, but will log for now
+			Logger.logException(e);
+		}
+		if (fPositionManager != null) {
+			fPositionManager.updatePositions(new DocumentEvent(this, start, lengthToReplace, changes));
+		}
+		fModificationStamp++;
+		fNextModificationStamp= Math.max(fModificationStamp, fNextModificationStamp);
+		resumePostNotificationProcessing();
+	}
+
+	private StructuredDocumentEvent updateModel(Object requester, int start, int lengthToReplace, String changes) {
+		StructuredDocumentEvent result = null;
+		IStructuredTextReParser reParser = getReParser();
+		// initialize the IStructuredTextReParser with the standard data
+		// that's
+		// always needed
+		reParser.initialize(requester, start, lengthToReplace, changes);
+		result = reParser.reparse();
+		// if result is null at this point, then there must be an error, since
+		// even if there
+		// was no change (either disallow due to readonly, or a person pasted
+		// the same thing
+		// they had selected) then a "NoChange" event should have been fired.
+		Assert.isNotNull(result, "no structuredDocument event was created in IStructuredDocument::updateStructuredDocument"); //$NON-NLS-1$
+		return result;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument#getPreferredLineDelimiter()
+	 */
+	public String getPreferredLineDelimiter() {
+		return getDefaultLineDelimiter();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.internal.provisional.document.IEncodedDocument#setPreferredLineDelimiter(java.lang.String)
+	 */
+	public void setPreferredLineDelimiter(String probableLineDelimiter) {
+		setInitialLineDelimiter(probableLineDelimiter);
+
+	}
+
+
+	/**
+	 * Class which implements the rewritable session for the SSE.
+	 * 
+	 */
+	static class StructuredDocumentRewriteSession extends DocumentRewriteSession {
+
+		/**
+		 * Creates a new session.
+		 * 
+		 * @param sessionType
+		 *            the type of this session
+		 */
+		protected StructuredDocumentRewriteSession(DocumentRewriteSessionType sessionType) {
+			super(sessionType);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension4#startRewriteSession(org.eclipse.jface.text.DocumentRewriteSessionType)
+	 */
+	public DocumentRewriteSession startRewriteSession(DocumentRewriteSessionType sessionType) throws IllegalStateException {
+		// delegate to sub-class, so UI threading is handled correctly
+		return internalStartRewriteSession(sessionType);
+	}
+
+	/**
+	 * NOT-API. Final protected so clients may call this method if needed, but
+	 * cannot override.
+	 * 
+	 * @param sessionType
+	 * @return
+	 * @throws IllegalStateException
+	 */
+	final protected DocumentRewriteSession internalStartRewriteSession(DocumentRewriteSessionType sessionType) throws IllegalStateException {
+		if (getActiveRewriteSession() != null)
+			throw new IllegalStateException("already in a rewrite session");
+
+		DocumentRewriteSession session = new StructuredDocumentRewriteSession(sessionType);
+		DocumentRewriteSessionEvent event = new DocumentRewriteSessionEvent(this, session, DocumentRewriteSessionEvent.SESSION_START);
+		fireDocumentRewriteSessionEvent(event);
+
+		ILineTracker tracker = getTracker();
+		if (tracker instanceof ILineTrackerExtension) {
+			ILineTrackerExtension extension = (ILineTrackerExtension) tracker;
+			extension.startRewriteSession(session);
+		}
+
+		startRewriteSessionOnPartitioners(session);
+
+		if (DocumentRewriteSessionType.SEQUENTIAL == sessionType)
+			startSequentialRewrite(false);
+		else if (DocumentRewriteSessionType.STRICTLY_SEQUENTIAL == sessionType)
+			startSequentialRewrite(true);
+
+		fActiveRewriteSession = session;
+		return session;
+	}
+
+	/**
+	 * Starts the given rewrite session.
+	 *
+	 * @param session the rewrite session
+	 * @since 2.0
+	 */
+	final void startRewriteSessionOnPartitioners(DocumentRewriteSession session) {
+		if (fDocumentPartitioners != null) {
+			Iterator e= fDocumentPartitioners.values().iterator();
+			while (e.hasNext()) {
+				Object partitioner= e.next();
+				if (partitioner instanceof IDocumentPartitionerExtension3) {
+					IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) partitioner;
+					extension.startRewriteSession(session);
+				}
+			}
+		}
+	}
+
+
+	public void stopRewriteSession(DocumentRewriteSession session) {
+		// delegate to sub-class, so UI threading is handled correctly
+		internalStopRewriteSession(session);
+	}
+
+	/**
+	 * NOT-API. Final protected so clients may call this method if needed, but
+	 * cannot override.
+	 * 
+	 * @param session
+	 */
+	final protected void internalStopRewriteSession(DocumentRewriteSession session) {
+		if (fActiveRewriteSession == session) {
+			DocumentRewriteSessionType sessionType = session.getSessionType();
+			if (DocumentRewriteSessionType.SEQUENTIAL == sessionType || DocumentRewriteSessionType.STRICTLY_SEQUENTIAL == sessionType)
+				stopSequentialRewrite();
+
+			stopRewriteSessionOnPartitioners(session);
+
+			ILineTracker tracker = getTracker();
+			if (tracker instanceof ILineTrackerExtension) {
+				ILineTrackerExtension extension = (ILineTrackerExtension) tracker;
+				extension.stopRewriteSession(session, get());
+			}
+
+			fActiveRewriteSession = null;
+			DocumentRewriteSessionEvent event = new DocumentRewriteSessionEvent(this, session, DocumentRewriteSessionEvent.SESSION_STOP);
+			fireDocumentRewriteSessionEvent(event);
+		}
+	}
+
+	/**
+	 * Stops the given rewrite session.
+	 *
+	 * @param session the rewrite session
+	 * @since 2.0
+	 */
+	final void stopRewriteSessionOnPartitioners(DocumentRewriteSession session) {
+		if (fDocumentPartitioners != null) {
+			DocumentPartitioningChangedEvent event= new DocumentPartitioningChangedEvent(this);
+			Iterator e= fDocumentPartitioners.keySet().iterator();
+			while (e.hasNext()) {
+				String partitioning= (String) e.next();
+				IDocumentPartitioner partitioner= (IDocumentPartitioner) fDocumentPartitioners.get(partitioning);
+				if (partitioner instanceof IDocumentPartitionerExtension3) {
+					IDocumentPartitionerExtension3 extension= (IDocumentPartitionerExtension3) partitioner;
+					extension.stopRewriteSession(session);
+					event.setPartitionChange(partitioning, 0, getLength());
+				}
+			}
+			if (!event.isEmpty())
+				fireDocumentPartitioningChanged(event);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension4#getActiveRewriteSession()
+	 */
+	public DocumentRewriteSession getActiveRewriteSession() {
+		return fActiveRewriteSession;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension4#addDocumentRewriteSessionListener(org.eclipse.jface.text.IDocumentRewriteSessionListener)
+	 */
+	public void addDocumentRewriteSessionListener(IDocumentRewriteSessionListener listener) {
+		synchronized (listenerLock) {
+			Assert.isNotNull(listener);
+			if (fDocumentRewriteSessionListeners == null) {
+				fDocumentRewriteSessionListeners = new ArrayList(1);
+			}
+			if (!fDocumentRewriteSessionListeners.contains(listener))
+				fDocumentRewriteSessionListeners.add(listener);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension4#removeDocumentRewriteSessionListener(org.eclipse.jface.text.IDocumentRewriteSessionListener)
+	 */
+	public void removeDocumentRewriteSessionListener(IDocumentRewriteSessionListener listener) {
+		synchronized (listenerLock) {
+
+			Assert.isNotNull(listener);
+			if (fDocumentRewriteSessionListeners != null)
+				fDocumentRewriteSessionListeners.remove(listener);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension4#replace(int, int,
+	 *      java.lang.String, long)
+	 */
+	public void replace(int offset, int length, String text, long modificationStamp) throws BadLocationException {
+		replaceText(this, offset, length, text, modificationStamp, true);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension4#set(java.lang.String,
+	 *      long)
+	 */
+	public void set(String text, long modificationStamp) {
+		// bug 151069 - overwrite read only regions when setting entire document
+		 replaceText(null, 0, getLength(), text, modificationStamp, true);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension4#getModificationStamp()
+	 */
+	public long getModificationStamp() {
+		return fModificationStamp;
+	}
+	
+	private long getNextModificationStamp() {
+		if (fNextModificationStamp == Long.MAX_VALUE || fNextModificationStamp == IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP)
+			fNextModificationStamp= 0;
+		else
+			fNextModificationStamp= fNextModificationStamp + 1;
+
+		return fNextModificationStamp;
+	}
+
+	/**
+	 * Fires an event, as specified, to the associated listeners.
+	 * 
+	 * @param event
+	 *            The event to fire, either a start or stop event.
+	 */
+	private void fireDocumentRewriteSessionEvent(final DocumentRewriteSessionEvent event) {
+		if (fDocumentRewriteSessionListeners == null || fDocumentRewriteSessionListeners.size() == 0)
+			return;
+
+		Object[] listeners = fDocumentRewriteSessionListeners.toArray();
+		for (int i = 0; i < listeners.length; i++) {
+			final IDocumentRewriteSessionListener l = (IDocumentRewriteSessionListener) listeners[i];
+			SafeRunner.run(new ISafeRunnable() {
+				public void run() throws Exception {
+					l.documentRewriteSessionChanged(event);
+				}
+				public void handleException(Throwable exception) {
+					// logged for us
+				}
+			});
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocumentRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocumentRegion.java
new file mode 100644
index 0000000..7fba9b3
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocumentRegion.java
@@ -0,0 +1,622 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (Intalio) - bug 300430 - String concatenation
+ *     David Carver (Intalio) - bug 300427 - Comparison of String Objects == or !=
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+
+
+public class BasicStructuredDocumentRegion implements IStructuredDocumentRegion {
+	private static final String TEXT_STORE_NOT_ASSIGNED = "text store not assigned yet"; //$NON-NLS-1$
+	private static final String UNDEFINED = "org.eclipse.wst.sse.core.structuredDocument.UNDEFINED"; //$NON-NLS-1$
+
+	private ITextRegionList _regions;
+	/**
+	 * has this region been removed from its document
+	 */
+	private static final byte MASK_IS_DELETED = 1;
+	/**
+	 * was this region terminated normally
+	 */
+	private static final byte MASK_IS_ENDED = 1 << 1;
+
+	private byte fIsDeletedOrEnded = 0;
+
+	/**
+	 * allow a pointer back to this nodes model
+	 */
+	private IStructuredDocument fParentDocument;
+	
+	protected int fLength;
+	private IStructuredDocumentRegion next = null;
+	private IStructuredDocumentRegion previous = null;
+	protected int start;
+
+	public BasicStructuredDocumentRegion() {
+		super();
+		_regions = new TextRegionListImpl();
+
+	}
+
+	/**
+	 * Even inside-this class uses of 'regions' should use this method, as
+	 * this is where (soft) memory management/reparsing, etc., will be
+	 * centralized.
+	 */
+	private ITextRegionList _getRegions() {
+
+		return _regions;
+	}
+
+	public void addRegion(ITextRegion aRegion) {
+		_getRegions().add(aRegion);
+	}
+
+	public void adjust(int i) {
+		start += i;
+	}
+
+	public void adjustLength(int i) {
+		fLength += i;
+	}
+
+	public void adjustStart(int i) {
+		start += i;
+	}
+
+	public void adjustTextLength(int i) {
+		// not supported
+
+	}
+
+	public boolean containsOffset(int i) {
+
+		return getStartOffset() <= i && i < getEndOffset();
+	}
+
+	public boolean containsOffset(ITextRegion containedRegion, int offset) {
+		return getStartOffset(containedRegion) <= offset && offset < getEndOffset(containedRegion);
+	}
+
+	public void equatePositions(ITextRegion region) {
+		start = region.getStart();
+		fLength = region.getLength();
+	}
+
+	/**
+	 * getEnd and getEndOffset are the same only for
+	 * IStructuredDocumentRegions
+	 */
+	public int getEnd() {
+		return start + fLength;
+	}
+
+	/**
+	 * getEnd and getEndOffset are the same only for
+	 * IStructuredDocumentRegions
+	 */
+	public int getEndOffset() {
+		return getEnd();
+	}
+
+	public int getEndOffset(ITextRegion containedRegion) {
+		return getStartOffset(containedRegion) + containedRegion.getLength();
+	}
+
+	public ITextRegion getFirstRegion() {
+		if (_getRegions() == null)
+			return null;
+		return _getRegions().get(0);
+	}
+
+	public String getFullText() {
+		String result = ""; //$NON-NLS-1$
+		try {
+			result = getParentDocument().get(start, fLength);
+		}
+		catch (BadLocationException e) {
+			// log for now, unless we find reason not to
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+		return result;
+	}
+
+	public String getFullText(ITextRegion aRegion) {
+		String result = ""; //$NON-NLS-1$
+		try {
+			int regionStart = aRegion.getStart();
+			int regionLength = aRegion.getLength();
+			result = fParentDocument.get(start + regionStart, regionLength);
+		}
+		catch (BadLocationException e) {
+			// log for now, unless we find reason not to
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+		return result;
+	}
+
+	public String getFullText(String context) {
+		// DMW: looping is faster than enumeration,
+		// so switched around 2/12/03
+		// Enumeration e = getRegions().elements();
+		ITextRegion region = null;
+		String result = ""; //$NON-NLS-1$
+		int length = getRegions().size();
+		StringBuffer sb = new StringBuffer(result);
+		for (int i = 0; i < length; i++) {
+			region = getRegions().get(i);
+			if (region.getType().equals(context))
+				sb.append(getFullText(region));
+		}
+		result = sb.toString();
+		return result;
+	}
+
+	public ITextRegion getLastRegion() {
+		if (_getRegions() == null)
+			return null;
+		return _getRegions().get(_getRegions().size() - 1);
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public IStructuredDocumentRegion getNext() {
+		return next;
+	}
+
+	public int getNumberOfRegions() {
+		return _getRegions().size();
+	}
+
+	public IStructuredDocument getParentDocument() {
+
+		return fParentDocument;
+	}
+
+	public IStructuredDocumentRegion getPrevious() {
+		return previous;
+	}
+
+	/**
+	 * The parameter offset refers to the overall offset in the document.
+	 */
+	public ITextRegion getRegionAtCharacterOffset(int offset) {
+		if (_getRegions() != null) {
+			int thisStartOffset = getStartOffset();
+			if (offset < thisStartOffset)
+				return null;
+			int thisEndOffset = getStartOffset() + getLength();
+			if (offset > thisEndOffset)
+				return null;
+			// transform the requested offset to the "scale" that
+			// regions are stored in, which are all relative to the
+			// start point.
+			// int transformedOffset = offset - getStartOffset();
+			//
+			ITextRegionList regions = getRegions();
+			int length = regions.size();
+			int low = 0;
+			int high = length;
+			int mid = 0;
+			// Binary search for the region
+			while (low < high) {
+				mid = low + ((high - low) >> 1);
+				ITextRegion region = regions.get(mid);
+				if (Debug.debugStructuredDocument) {
+					System.out.println("region(s) in IStructuredDocumentRegion::getRegionAtCharacterOffset: " + region); //$NON-NLS-1$
+					System.out.println("       requested offset: " + offset); //$NON-NLS-1$
+					// System.out.println(" transformedOffset: " +
+					// transformedOffset); //$NON-NLS-1$
+					System.out.println("       region start: " + region.getStart()); //$NON-NLS-1$
+					System.out.println("       region end: " + region.getEnd()); //$NON-NLS-1$
+					System.out.println("       region type: " + region.getType()); //$NON-NLS-1$
+					System.out.println("       region class: " + region.getClass()); //$NON-NLS-1$
+
+				}
+				// Region is before this one
+				if (offset < region.getStart() + thisStartOffset)
+					high = mid;
+				else if (offset > (region.getEnd() + thisStartOffset - 1))
+					low = mid + 1;
+				else
+					return region;
+			}
+		}
+		return null;
+	}
+
+	public ITextRegionList getRegions() {
+		return _getRegions();
+	}
+
+	/**
+	 * getStart and getStartOffset are the same only for
+	 * IStrucutredDocumentRegions
+	 */
+	public int getStart() {
+		return start;
+	}
+
+	/**
+	 * getStart and getStartOffset are the same only for
+	 * IStrucutredDocumentRegions
+	 */
+	public int getStartOffset() {
+		return getStart();
+	}
+
+	public int getStartOffset(ITextRegion containedRegion) {
+		// assert: containedRegion can not be null
+		// (might be performance hit if literally put in assert call,
+		// but containedRegion can not be null). Needs to be checked
+		// by calling code.
+		return getStartOffset() + containedRegion.getStart();
+	}
+
+	public String getText() {
+		String result = null;
+		try {
+			if (fParentDocument == null) {
+				// likely to happen during inspecting
+				result = TEXT_STORE_NOT_ASSIGNED;
+			}
+			else {
+				result = fParentDocument.get(start, fLength);
+			}
+		}
+		catch (BadLocationException e) {
+			// log for now, unless we find reason not to
+			Logger.log(Logger.INFO, e.getMessage());
+		}
+		return result;
+	}
+
+	public String getText(ITextRegion aRegion) {
+		// assert: aRegion can not be null
+		// (might be performance hit if literally put in assert call,
+		// but aRegion can not be null). Needs to be checked
+		// by calling code.
+		try {
+			return fParentDocument.get(this.getStartOffset(aRegion), aRegion.getTextLength());
+		}
+		catch (BadLocationException e) {
+			Logger.logException(e);
+		}
+		return ""; //$NON-NLS-1$
+	}
+
+	/**
+	 * Returns the text of the first region with the matching context type
+	 */
+	public String getText(String context) {
+		// DMW: looping is faster than enumeration,
+		// so switched around 2/12/03
+		// Enumeration e = getRegions().elements();
+		ITextRegion region = null;
+		String result = ""; //$NON-NLS-1$
+		int length = getRegions().size();
+		for (int i = 0; i < length; i++) {
+			region = getRegions().get(i);
+			if (region.getType().equals(context)) {
+				result = getText(region);
+				break;
+			}
+		}
+		return result;
+	}
+
+	public int getTextEnd() {
+		return start + fLength;
+	}
+
+	/**
+	 * @return int
+	 */
+	public int getTextEndOffset() {
+		ITextRegion region = _getRegions().get(_getRegions().size() - 1);
+		return getStartOffset() + region.getTextEnd();
+	}
+
+	public int getTextEndOffset(ITextRegion containedRegion) {
+		return getStartOffset(containedRegion) + containedRegion.getTextLength();
+	}
+
+	public int getTextLength() {
+		return fLength;
+	}
+
+	/**
+	 * Provides the type of IStructuredDocumentRegion ... not to be confused
+	 * with type of XML node! This is subclassed, if something other than type
+	 * of first region is desired.
+	 * 
+	 */
+	public String getType() {
+		String result = UNDEFINED;
+		ITextRegionList subregions = getRegions();
+		if (subregions != null && subregions.size() > 0) {
+			ITextRegion firstRegion = subregions.get(0);
+			if (firstRegion != null) {
+				result = firstRegion.getType();
+			}
+		}
+		return result;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.text.IStructuredDocumentRegion#isDeleted()
+	 */
+	public boolean isDeleted() {
+		return (fIsDeletedOrEnded & MASK_IS_DELETED) != 0 || (fParentDocument == null);
+	}
+
+	/**
+	 * 
+	 * @return boolean
+	 */
+	public boolean isEnded() {
+		return (fIsDeletedOrEnded & MASK_IS_ENDED) != 0;
+	}
+
+	public boolean sameAs(IStructuredDocumentRegion region, int shift) {
+		boolean result = false;
+		// if region == null, we return false;
+		if (region != null) {
+			// if the regions are the same instance, they are equal
+			if (this == region) {
+				result = true;
+			}
+			else {
+				// this is the non-trivial part
+				// note: we change for type first, then start offset and end
+				// offset,
+				// since that would decide many cases right away and avoid the
+				// text comparison
+				if (getType().equals(region.getType())) {
+					if (sameOffsetsAs(region, shift) && sameTextAs(region, shift)) {
+						result = true;
+					}
+				}
+
+			}
+		}
+		return result;
+	}
+
+	public boolean sameAs(ITextRegion oldRegion, IStructuredDocumentRegion newDocumentRegion, ITextRegion newRegion, int shift) {
+		boolean result = false;
+		// if any region is null, we return false (even if both are!)
+		if ((oldRegion != null) && (newRegion != null)) {
+			// if the regions are the same instance, they are equal
+			if (oldRegion == newRegion) {
+				result = true;
+			}
+			else {
+				// this is the non-trivial part
+				// note: we change for type first, then start offset and end
+				// offset,
+				// since that would decide many cases right away and avoid the
+				// text comparison
+				if (oldRegion.getType().equals(newRegion.getType())) {
+					if (sameOffsetsAs(oldRegion, newDocumentRegion, newRegion, shift)) {
+						if (sameTextAs(oldRegion, newDocumentRegion, newRegion, shift)) {
+							result = true;
+						}
+					}
+				}
+			}
+
+		}
+
+		return result;
+	}
+
+	private boolean sameOffsetsAs(IStructuredDocumentRegion region, int shift) {
+		if (getStartOffset() == region.getStartOffset() - shift) {
+			if (getEndOffset() == region.getEndOffset() - shift) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	private boolean sameOffsetsAs(ITextRegion oldRegion, IStructuredDocumentRegion documentRegion, ITextRegion newRegion, int shift) {
+		if (getStartOffset(oldRegion) == documentRegion.getStartOffset(newRegion) - shift) {
+			if (getEndOffset(oldRegion) == documentRegion.getEndOffset(newRegion) - shift) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	private boolean sameTextAs(IStructuredDocumentRegion region, int shift) {
+		boolean result = false;
+		try {
+			if (getText().equals(region.getText())) {
+				result = true;
+			}
+		}
+		// ISSUE: we should not need this
+		catch (StringIndexOutOfBoundsException e) {
+			result = false;
+		}
+
+		return result;
+	}
+
+	private boolean sameTextAs(ITextRegion oldRegion, IStructuredDocumentRegion documentRegion, ITextRegion newRegion, int shift) {
+		boolean result = false;
+
+		if (getText(oldRegion).equals(documentRegion.getText(newRegion))) {
+			result = true;
+		}
+
+		return result;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.text.IStructuredDocumentRegion#setDelete(boolean)
+	 */
+	public void setDeleted(boolean isDeleted) {
+		if (isDeleted)
+			fIsDeletedOrEnded |= MASK_IS_DELETED;
+		else
+			fIsDeletedOrEnded &= ~MASK_IS_DELETED;
+	}
+
+	/**
+	 * 
+	 * @param newHasEnd
+	 *            boolean
+	 */
+	public void setEnded(boolean newHasEnd) {
+		if (newHasEnd)
+			fIsDeletedOrEnded |= MASK_IS_ENDED;
+		else
+			fIsDeletedOrEnded &= ~MASK_IS_ENDED;
+	}
+
+	public void setLength(int newLength) {
+		// textLength = newLength;
+		fLength = newLength;
+	}
+
+	public void setNext(IStructuredDocumentRegion newNext) {
+		next = newNext;
+	}
+
+	public void setParentDocument(IStructuredDocument document) {
+		fParentDocument = document;
+
+	}
+
+	public void setPrevious(IStructuredDocumentRegion newPrevious) {
+		previous = newPrevious;
+	}
+
+	public void setRegions(ITextRegionList containedRegions) {
+		_regions = containedRegions;
+	}
+
+	public void setStart(int newStart) {
+		start = newStart;
+	}
+
+	public String toString() {
+		// NOTE: if the document held by any region has been updated and the
+		// region offsets have not
+		// yet been updated, the output from this method invalid.
+		// Also note, this method can not be changed, without "breaking"
+		// unit tests, since some of them compare current results to previous
+		// results.
+		String result = null;
+		result = "[" + getStart() + ", " + getEnd() + "] (" + getText() + ")"; //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+		return result;
+	}
+
+	private void updateDownStreamRegions(ITextRegion changedRegion, int lengthDifference) {
+		int listLength = _getRegions().size();
+		int startIndex = 0;
+		// first, loop through to find index of where to start
+		for (int i = 0; i < listLength; i++) {
+			ITextRegion region = _getRegions().get(i);
+			if (region == changedRegion) {
+				startIndex = i;
+				break;
+			}
+		}
+		// now, beginning one past the one that was changed, loop
+		// through to end of list, adjusting the start postions.
+		startIndex++;
+		for (int j = startIndex; j < listLength; j++) {
+			ITextRegion region = _getRegions().get(j);
+			region.adjustStart(lengthDifference);
+		}
+	}
+
+	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion structuredDocumentRegion, String changes, int requestStart, int lengthToReplace) {
+		StructuredDocumentEvent result = null;
+		int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
+		// Get the region pointed to by the requestStart postion, and give
+		// that region a chance to effect
+		// the update.
+		ITextRegion region = getRegionAtCharacterOffset(requestStart);
+		// if there is no region, then the requested changes must come right
+		// after the
+		// node (and right after the last region). This happens, for example,
+		// when someone
+		// types something at the end of the document, or more commonly, when
+		// they are right
+		// at the beginning of one node, and the dirty start is therefore
+		// calculated to be the
+		// previous node.
+		// So, in this case, we'll give the last region a chance to see if it
+		// wants to
+		// swallow the requested changes -- but only for inserts -- deletes
+		// and "replaces"
+		// should be reparsed if they are in these border regions, and only if
+		// the
+		if ((region == null) && (lengthToReplace == 0)) {
+			region = _getRegions().get(_getRegions().size() - 1);
+			// make sure the region is contiguous
+			if (getEndOffset(region) == requestStart) {
+				result = region.updateRegion(requester, this, changes, requestStart, lengthToReplace);
+			}
+		}
+		else {
+			if (region != null) {
+				//
+				// If the requested change spans more than one region, then
+				// we don't give the region a chance to update.
+				if ((containsOffset(region, requestStart)) && (containsOffset(region, requestStart + lengthToReplace))) {
+					result = region.updateRegion(requester, this, changes, requestStart, lengthToReplace);
+				}
+			}
+		}
+		// if result is not null, then we need to update the start and end
+		// postions of the regions that follow this one
+		// if result is null, then apply the flatnode specific checks on what
+		// it can change
+		// (i.e. more than one region, but no change to the node itself)
+		if (result != null) {
+			// That is, a region decided it could handle the change and
+			// created
+			// a region changed event.
+			Assert.isTrue(result instanceof RegionChangedEvent, "Program Error"); //$NON-NLS-1$
+			updateDownStreamRegions(((RegionChangedEvent) result).getRegion(), lengthDifference);
+			// PLUS, we need to update our own node end point (length)
+			setLength(getLength() + lengthDifference);
+		}
+
+		return result;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/CharSequenceReader.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/CharSequenceReader.java
new file mode 100644
index 0000000..6ab29b5
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/CharSequenceReader.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+import java.io.IOException;
+import java.io.Reader;
+
+public class CharSequenceReader extends Reader {
+	private int fCurrentPosition;
+	private int fMaximumReadOffset;
+
+	private CharSequence fOriginalSource;
+
+	/**
+	 *  
+	 */
+	CharSequenceReader() {
+		super();
+	}
+
+
+	public CharSequenceReader(CharSequence originalSource, int offset, int length) {
+		// ISSUE: should we "fail fast" if requested length is more than there
+		// is?
+		fOriginalSource = originalSource;
+		int startOffset = offset;
+		int maxRequestedOffset = startOffset + length;
+		int maxPossibleOffset = 0 + originalSource.length();
+		fMaximumReadOffset = Math.min(maxRequestedOffset, maxPossibleOffset);
+
+		fCurrentPosition = startOffset;
+
+	}
+
+	/**
+	 * @param lockObject
+	 */
+	CharSequenceReader(Object lockObject) {
+		super(lockObject);
+		// for thread safety, may need to add back locking mechanism
+		// in our custom constructor. This constructor left here just
+		// for a reminder.
+	}
+
+	public void close() throws IOException {
+		// nothing to do when we close
+		// (may be to eventually "unlock" or null out some varibles
+		// just for hygene.
+		// or, perhaps if already closed once throw IOException? for
+		// consistency?
+	}
+
+	/**
+	 * @return Returns the originalSource.
+	 * @deprecated - only temporarily public, should be 'default' eventually
+	 *             or go away altogether.
+	 */
+	public CharSequence getOriginalSource() {
+		return fOriginalSource;
+	}
+
+	public int read() {
+		int result = -1;
+		if (fCurrentPosition < fMaximumReadOffset) {
+			result = fOriginalSource.charAt(fCurrentPosition++);
+		}
+		return result;
+	}
+
+	/**
+	 * Read characters into a portion of an array. This method will block
+	 * until some input is available, an I/O error occurs, or the end of the
+	 * stream is reached.
+	 * 
+	 * @param cbuf
+	 *            Destination buffer
+	 * @param off
+	 *            Offset at which to start storing characters
+	 * @param len
+	 *            Maximum number of characters to read
+	 * 
+	 * @return The number of characters read, or -1 if the end of the stream
+	 *         has been reached
+	 * 
+	 * @exception IOException
+	 *                If an I/O error occurs
+	 */
+
+	public int read(char[] cbuf, int off, int len) throws IOException {
+		int charsToRead = -1;
+		// if already over max, just return -1
+		// remember, currentPosition is what is getting ready to be read
+		// (that is, its already been incremented in read()).
+		if (fCurrentPosition < fMaximumReadOffset) {
+
+
+			int buffMaxToRead = cbuf.length - off;
+			int minRequested = Math.min(buffMaxToRead, len);
+			int lengthRemaining = fMaximumReadOffset - fCurrentPosition;
+			charsToRead = Math.min(minRequested, lengthRemaining);
+
+
+			CharSequence seq = fOriginalSource.subSequence(fCurrentPosition, fCurrentPosition + charsToRead);
+			// for now, hard assumption that original is a String since source
+			// is assumed to be document, or text store
+			String seqString = (String) seq;
+			seqString.getChars(0, seqString.length(), cbuf, off);
+
+
+
+			fCurrentPosition = fCurrentPosition + charsToRead;
+
+
+		}
+		return charsToRead;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/CoreNodeList.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/CoreNodeList.java
new file mode 100644
index 0000000..6acd927
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/CoreNodeList.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+
+
+import java.util.Enumeration;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList;
+
+
+public class CoreNodeList implements IStructuredDocumentRegionList {
+	int countedLength;
+	int currentIndex = -1;
+
+	IStructuredDocumentRegion[] flatNodes;
+	IStructuredDocumentRegion head;
+
+	/**
+	 * CoreNodeList constructor comment.
+	 */
+	public CoreNodeList() {
+		super();
+		// create an array, even if zero length
+		flatNodes = new IStructuredDocumentRegion[0];
+	}
+
+	public CoreNodeList(IStructuredDocumentRegion newHead) {
+		super();
+		// save head
+		head = newHead;
+		int count = 0;
+		IStructuredDocumentRegion countNode = newHead;
+		// we have to go through the list once, to get its
+		// length in order to create the array
+		while (countNode != null) {
+			count++;
+			countNode = countNode.getNext();
+		}
+		// create an array, even if zero length
+		flatNodes = new IStructuredDocumentRegion[count];
+		// start countNode over again, so to speak.
+		countNode = newHead;
+		count = 0;
+		while (countNode != null) {
+			flatNodes[count++] = countNode;
+			countNode = countNode.getNext();
+		}
+		if (count > 0) {
+			currentIndex = 0;
+			// else it stays at -1 initialized at object creation
+			//
+			// save length
+			countedLength = count;
+		}
+	}
+
+	public CoreNodeList(IStructuredDocumentRegion start, IStructuredDocumentRegion end) {
+		super();
+		// save head
+		head = start;
+		int count = 0;
+		IStructuredDocumentRegion countNode = start;
+		if ((start == null) || (end == null)) {
+			// error condition
+			//throw new IllegalArgumentException("Must provide start and end
+			// nodes to construct CoreNodeList");
+		} else {
+			count = 1;
+			while ((countNode != null) && (countNode != end)) {
+				count++;
+				countNode = countNode.getNext();
+			}
+		}
+		// if we ended because the last one was null,
+		// backup one.
+		if (countNode == null)
+			count--;
+		if (count < 0) {
+			count = 0;
+		}
+		flatNodes = new IStructuredDocumentRegion[count];
+		if (count > 0) {
+			flatNodes[0] = countNode = start;
+			for (int i = 1; i < count; i++) {
+				flatNodes[i] = flatNodes[i - 1].getNext();
+			}
+
+		}
+		currentIndex = 0;
+		countedLength = count;
+	}
+
+	public Enumeration elements() {
+		StructuredDocumentRegionEnumeration result = null;
+		if ((flatNodes != null) && (flatNodes.length > 0))
+			result = new StructuredDocumentRegionEnumeration(flatNodes[0], flatNodes[flatNodes.length - 1]);
+		else
+			result = new StructuredDocumentRegionEnumeration(null);
+		return result;
+	}
+
+	public int getLength() {
+		return flatNodes.length;
+	}
+
+	public boolean includes(Object o) {
+		if (flatNodes == null)
+			return false;
+		for (int i = 0; i < flatNodes.length; i++)
+			if (flatNodes[i] == o)
+				return true;
+		return false;
+	}
+
+	public IStructuredDocumentRegion item(int i) {
+		return flatNodes[i];
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/DeleteEqualPositionUpdater.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/DeleteEqualPositionUpdater.java
new file mode 100644
index 0000000..e33783e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/DeleteEqualPositionUpdater.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.DefaultPositionUpdater;
+
+/**
+ * Follows the behavior of DefaultPositionUpdater except in addition to
+ * deleting/overwriting text which completely contains the position deletes
+ * the position, deleting text that equals the text in position also deletes
+ * the position.
+ * 
+ * @see org.eclipse.jface.text.DefaultPositionUpdater
+ */
+public class DeleteEqualPositionUpdater extends DefaultPositionUpdater {
+
+	/**
+	 * @param category
+	 */
+	public DeleteEqualPositionUpdater(String category) {
+		super(category);
+	}
+
+	/**
+	 * Determines whether the currently investigated position has been deleted
+	 * by the replace operation specified in the current event. If so, it
+	 * deletes the position and removes it from the document's position
+	 * category.
+	 * 
+	 * NOTE: position is deleted if current event completely overwrites
+	 * position OR if current event deletes the area surrounding/including the
+	 * position
+	 * 
+	 * @return <code>true</code> if position has been deleted
+	 */
+	protected boolean notDeleted() {
+		// position is deleted if current event completely overwrites position
+		// OR if
+		// current event deletes the area surrounding/including the position
+		if ((fOffset < fPosition.offset && (fPosition.offset + fPosition.length < fOffset + fLength)) || (fOffset <= fPosition.offset && (fPosition.offset + fPosition.length <= fOffset + fLength) && fReplaceLength == 0)) {
+
+			fPosition.delete();
+
+			try {
+				fDocument.removePosition(getCategory(), fPosition);
+			} catch (BadPositionCategoryException x) {
+			}
+
+			return false;
+		}
+
+		return true;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/GenericPositionManager.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/GenericPositionManager.java
new file mode 100644
index 0000000..0a422a3
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/GenericPositionManager.java
@@ -0,0 +1,409 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+
+package org.eclipse.wst.sse.core.internal.text;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.DefaultPositionUpdater;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IPositionUpdater;
+import org.eclipse.jface.text.Position;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+
+/**
+ * Based on the Position management methods from
+ * org.eclipse.jface.text.AbstractDocument
+ */
+
+public class GenericPositionManager {
+	private CharSequence fCharSequence;
+
+
+
+	private Map fPositions;
+	/** All registered document position updaters */
+	private List fPositionUpdaters;
+
+	/**
+	 * don't allow instantiation with out document pointer
+	 * 
+	 */
+	private GenericPositionManager() {
+		super();
+	}
+
+	/**
+	 * 
+	 */
+	public GenericPositionManager(CharSequence charSequence) {
+		this();
+		// we only use charSequence for "length", to
+		// made more generic than "document" even "text store"
+		fCharSequence = charSequence;
+		completeInitialization();
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#addPosition(org.eclipse.jface.text.Position)
+	 */
+	public void addPosition(Position position) throws BadLocationException {
+		try {
+			addPosition(IDocument.DEFAULT_CATEGORY, position);
+		}
+		catch (BadPositionCategoryException e) {
+		}
+	}
+
+
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#addPosition(java.lang.String,
+	 *      org.eclipse.jface.text.Position)
+	 */
+	public synchronized void addPosition(String category, Position position) throws BadLocationException, BadPositionCategoryException {
+
+		if ((0 > position.offset) || (0 > position.length) || (position.offset + position.length > getDocumentLength()))
+			throw new BadLocationException();
+
+		if (category == null)
+			throw new BadPositionCategoryException();
+
+		List list = (List) fPositions.get(category);
+		if (list == null)
+			throw new BadPositionCategoryException();
+
+		list.add(computeIndexInPositionList(list, position.offset), position);
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#addPositionCategory(java.lang.String)
+	 */
+	public void addPositionCategory(String category) {
+
+		if (category == null)
+			return;
+
+		if (!containsPositionCategory(category))
+			fPositions.put(category, new ArrayList());
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#addPositionUpdater(org.eclipse.jface.text.IPositionUpdater)
+	 */
+	public void addPositionUpdater(IPositionUpdater updater) {
+		insertPositionUpdater(updater, fPositionUpdaters.size());
+	}
+
+
+	/**
+	 * Initializes document listeners, positions, and position updaters. Must
+	 * be called inside the constructor after the implementation plug-ins have
+	 * been set.
+	 */
+	protected void completeInitialization() {
+
+		fPositions = new HashMap();
+		fPositionUpdaters = new ArrayList();
+
+		addPositionCategory(IDocument.DEFAULT_CATEGORY);
+		addPositionUpdater(new DefaultPositionUpdater(IDocument.DEFAULT_CATEGORY));
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#computeIndexInCategory(java.lang.String,
+	 *      int)
+	 */
+	public int computeIndexInCategory(String category, int offset) throws BadLocationException, BadPositionCategoryException {
+
+		if (0 > offset || offset > getDocumentLength())
+			throw new BadLocationException();
+
+		List c = (List) fPositions.get(category);
+		if (c == null)
+			throw new BadPositionCategoryException();
+
+		return computeIndexInPositionList(c, offset);
+	}
+
+
+	/**
+	 * Computes the index in the list of positions at which a position with
+	 * the given offset would be inserted. The position is supposed to become
+	 * the first in this list of all positions with the same offset.
+	 * 
+	 * @param positions
+	 *            the list in which the index is computed
+	 * @param offset
+	 *            the offset for which the index is computed
+	 * @return the computed index
+	 * 
+	 * @see IDocument#computeIndexInCategory(String, int)
+	 */
+	protected synchronized int computeIndexInPositionList(List positions, int offset) {
+
+		if (positions.size() == 0)
+			return 0;
+
+		int left = 0;
+		int right = positions.size() - 1;
+		int mid = 0;
+		Position p = null;
+
+		while (left < right) {
+
+			mid = (left + right) / 2;
+
+			p = (Position) positions.get(mid);
+			if (offset < p.getOffset()) {
+				if (left == mid)
+					right = left;
+				else
+					right = mid - 1;
+			}
+			else if (offset > p.getOffset()) {
+				if (right == mid)
+					left = right;
+				else
+					left = mid + 1;
+			}
+			else if (offset == p.getOffset()) {
+				left = right = mid;
+			}
+
+		}
+
+		int pos = left;
+		p = (Position) positions.get(pos);
+		if (offset > p.getOffset()) {
+			// append to the end
+			pos++;
+		}
+		else {
+			// entry will became the first of all entries with the same
+			// offset
+			do {
+				--pos;
+				if (pos < 0)
+					break;
+				p = (Position) positions.get(pos);
+			}
+			while (offset == p.getOffset());
+			++pos;
+		}
+
+		Assert.isTrue(0 <= pos && pos <= positions.size());
+
+		return pos;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#containsPosition(java.lang.String,
+	 *      int, int)
+	 */
+	public boolean containsPosition(String category, int offset, int length) {
+
+		if (category == null)
+			return false;
+
+		List list = (List) fPositions.get(category);
+		if (list == null)
+			return false;
+
+		int size = list.size();
+		if (size == 0)
+			return false;
+
+		int index = computeIndexInPositionList(list, offset);
+		if (index < size) {
+			Position p = (Position) list.get(index);
+			while (p != null && p.offset == offset) {
+				if (p.length == length)
+					return true;
+				++index;
+				p = (index < size) ? (Position) list.get(index) : null;
+			}
+		}
+
+		return false;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#containsPositionCategory(java.lang.String)
+	 */
+	public boolean containsPositionCategory(String category) {
+		if (category != null)
+			return fPositions.containsKey(category);
+		return false;
+	}
+
+
+
+	public int getDocumentLength() {
+		return fCharSequence.length();
+	}
+
+	/**
+	 * Returns all positions managed by the document grouped by category.
+	 * 
+	 * @return the document's positions
+	 */
+	protected Map getDocumentManagedPositions() {
+		return fPositions;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#getPositionCategories()
+	 */
+	public String[] getPositionCategories() {
+		String[] categories = new String[fPositions.size()];
+		Iterator keys = fPositions.keySet().iterator();
+		for (int i = 0; i < categories.length; i++)
+			categories[i] = (String) keys.next();
+		return categories;
+	}
+
+
+	public Position[] getPositions(String category) throws BadPositionCategoryException {
+
+		if (category == null)
+			throw new BadPositionCategoryException();
+
+		List c = (List) fPositions.get(category);
+		if (c == null)
+			throw new BadPositionCategoryException();
+
+		Position[] positions = new Position[c.size()];
+		c.toArray(positions);
+		return positions;
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#getPositionUpdaters()
+	 */
+	public IPositionUpdater[] getPositionUpdaters() {
+		IPositionUpdater[] updaters = new IPositionUpdater[fPositionUpdaters.size()];
+		fPositionUpdaters.toArray(updaters);
+		return updaters;
+	}
+
+
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#insertPositionUpdater(org.eclipse.jface.text.IPositionUpdater,
+	 *      int)
+	 */
+	public synchronized void insertPositionUpdater(IPositionUpdater updater, int index) {
+
+		for (int i = fPositionUpdaters.size() - 1; i >= 0; i--) {
+			if (fPositionUpdaters.get(i) == updater)
+				return;
+		}
+
+		if (index == fPositionUpdaters.size())
+			fPositionUpdaters.add(updater);
+		else
+			fPositionUpdaters.add(index, updater);
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#removePosition(org.eclipse.jface.text.Position)
+	 */
+	public void removePosition(Position position) {
+		try {
+			removePosition(IDocument.DEFAULT_CATEGORY, position);
+		}
+		catch (BadPositionCategoryException e) {
+		}
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#removePosition(java.lang.String,
+	 *      org.eclipse.jface.text.Position)
+	 */
+	public synchronized void removePosition(String category, Position position) throws BadPositionCategoryException {
+
+		if (position == null)
+			return;
+
+		if (category == null)
+			throw new BadPositionCategoryException();
+
+		List c = (List) fPositions.get(category);
+		if (c == null)
+			throw new BadPositionCategoryException();
+
+		// remove based on identity not equality
+		int size = c.size();
+		for (int i = 0; i < size; i++) {
+			if (position == c.get(i)) {
+				c.remove(i);
+				return;
+			}
+		}
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#removePositionCategory(java.lang.String)
+	 */
+	public void removePositionCategory(String category) throws BadPositionCategoryException {
+
+		if (category == null)
+			return;
+
+		if (!containsPositionCategory(category))
+			throw new BadPositionCategoryException();
+
+		fPositions.remove(category);
+	}
+
+	/*
+	 * @see org.eclipse.jface.text.IDocument#removePositionUpdater(org.eclipse.jface.text.IPositionUpdater)
+	 */
+	public synchronized void removePositionUpdater(IPositionUpdater updater) {
+		for (int i = fPositionUpdaters.size() - 1; i >= 0; i--) {
+			if (fPositionUpdaters.get(i) == updater) {
+				fPositionUpdaters.remove(i);
+				return;
+			}
+		}
+	}
+
+
+	/**
+	 * Updates all positions of all categories to the change described by the
+	 * document event. All registered document updaters are called in the
+	 * sequence they have been arranged. Uses a robust iterator.
+	 * 
+	 * @param event
+	 *            the document event describing the change to which to adapt
+	 *            the positions
+	 */
+	protected synchronized void updatePositions(DocumentEvent event) {
+		List list = new ArrayList(fPositionUpdaters);
+		Iterator e = list.iterator();
+		while (e.hasNext()) {
+			IPositionUpdater u = (IPositionUpdater) e.next();
+			u.update(event);
+		}
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/IExecutionDelegatable.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/IExecutionDelegatable.java
new file mode 100644
index 0000000..03ed267
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/IExecutionDelegatable.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+import org.eclipse.wst.sse.core.internal.IExecutionDelegate;
+
+public interface IExecutionDelegatable {
+
+	void setExecutionDelegate(IExecutionDelegate executionDelegate);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/IRegionComparible.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/IRegionComparible.java
new file mode 100644
index 0000000..3230439
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/IRegionComparible.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+public interface IRegionComparible {
+	boolean regionMatches(int offset, int length, String stringToCompare);
+
+	boolean regionMatchesIgnoreCase(int offset, int length, String stringToCompare);
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/JobSafeStructuredDocument.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/JobSafeStructuredDocument.java
new file mode 100644
index 0000000..502b508
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/JobSafeStructuredDocument.java
@@ -0,0 +1,249 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+import java.util.Stack;
+
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.jobs.ILock;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentRewriteSession;
+import org.eclipse.jface.text.DocumentRewriteSessionType;
+import org.eclipse.wst.sse.core.internal.IExecutionDelegate;
+import org.eclipse.wst.sse.core.internal.ILockable;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+
+/**
+ * An IStructuredDocument that performs most of its computation and event
+ * notification through an IExecutionDelegate.
+ * 
+ * If the delegate has not been set, we execute on current thread, like
+ * "normal". This is the case for normal non-editor use (which should still,
+ * ultimately, be protected by a scheduling rule). For every operation, a
+ * runnable is created, even if later (in the execution delegate instance) it
+ * is decided nothing special is needed (that is, in fact being called from an
+ * editor's display thread, in which case its just executed) in the UI.
+ */
+public class JobSafeStructuredDocument extends BasicStructuredDocument implements IExecutionDelegatable, ILockable {
+
+	private static abstract class JobSafeRunnable implements ISafeRunnable {
+		public void handleException(Throwable exception) {
+			// logged in SafeRunner
+		}
+	}
+	
+	private Stack fExecutionDelegates = new Stack();
+	private ILock fLockable = Job.getJobManager().newLock();
+
+	public JobSafeStructuredDocument() {
+		super();
+	}
+
+
+	public JobSafeStructuredDocument(RegionParser parser) {
+		super(parser);
+	}
+
+
+	/**
+	 * 
+	 */
+	protected final void acquireLock() {
+		getLockObject().acquire();
+	}
+
+	private IExecutionDelegate getExecutionDelegate() {
+		if (!fExecutionDelegates.isEmpty())
+			return (IExecutionDelegate) fExecutionDelegates.peek();
+		return null;
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.ILockable#getLock()
+	 */
+
+	public ILock getLockObject() {
+		return fLockable;
+	}
+
+
+	/**
+	 * 
+	 */
+	protected final void releaseLock() {
+		getLockObject().release();
+	}
+	
+	/*
+	 * @see org.eclipse.jface.text.IDocument.replace(int, int, String)
+	 */
+	public void replace(final int offset, final int length, final String text) throws BadLocationException {
+		IExecutionDelegate delegate = getExecutionDelegate();
+		if (delegate == null) {
+			super.replace(offset, length, text);
+		}
+		else {
+			JobSafeRunnable runnable = new JobSafeRunnable() {
+				public void run() throws Exception {
+					JobSafeStructuredDocument.super.replace(offset, length, text);
+				}
+			};
+			delegate.execute(runnable);
+		}
+	}
+	
+	/*
+	 * @see org.eclipse.jface.text.IDocumentExtension4.replace(int, int, String, long)
+	 */
+	public void replace(final int offset, final int length, final String text, final long modificationStamp) throws BadLocationException {
+		IExecutionDelegate delegate = getExecutionDelegate();
+		if (delegate == null) {
+			super.replace(offset, length, text, modificationStamp);
+		}
+		else {
+			JobSafeRunnable runnable = new JobSafeRunnable() {
+				public void run() throws Exception {
+					JobSafeStructuredDocument.super.replace(offset, length, text, modificationStamp);
+				}
+			};
+			delegate.execute(runnable);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument#replaceText(java.lang.Object, int, int, java.lang.String)
+	 */
+	public StructuredDocumentEvent replaceText(final Object requester, final int start, final int replacementLength, final String changes) {
+		StructuredDocumentEvent event = null;
+		IExecutionDelegate delegate = getExecutionDelegate();
+		if (delegate == null) {
+			event = super.replaceText(requester, start, replacementLength, changes);
+		}
+		else {
+			final Object[] resultSlot = new Object[1];
+			JobSafeRunnable runnable = new JobSafeRunnable() {
+				public void run() throws Exception {
+					resultSlot[0] = JobSafeStructuredDocument.super.replaceText(requester, start, replacementLength, changes);
+				}
+			};
+			delegate.execute(runnable);
+			event = (StructuredDocumentEvent) resultSlot[0];
+		}
+		return event;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument#replaceText(java.lang.Object, int, int, java.lang.String, boolean)
+	 */
+	public StructuredDocumentEvent replaceText(final Object requester, final int start, final int replacementLength, final String changes, final boolean ignoreReadOnlySettings) {
+		StructuredDocumentEvent event = null;
+		IExecutionDelegate delegate = getExecutionDelegate();
+		if (delegate == null) {
+			event = super.replaceText(requester, start, replacementLength, changes, ignoreReadOnlySettings);
+		}
+		else {
+			final Object[] resultSlot = new Object[1];
+			JobSafeRunnable runnable = new JobSafeRunnable() {
+				public void run() throws Exception {
+					resultSlot[0] = JobSafeStructuredDocument.super.replaceText(requester, start, replacementLength, changes, ignoreReadOnlySettings);
+				}
+
+				public void handleException(Throwable exception) {
+					resultSlot[0] = new NoChangeEvent(JobSafeStructuredDocument.this, requester, changes, start, replacementLength);
+					super.handleException(exception);
+				}
+			};
+			delegate.execute(runnable);
+			event = (StructuredDocumentEvent) resultSlot[0];
+		}
+		return event;
+	}
+
+	public void setExecutionDelegate(IExecutionDelegate delegate) {
+		if (delegate != null)
+			fExecutionDelegates.push(delegate);
+		else if (!fExecutionDelegates.isEmpty())
+			fExecutionDelegates.pop();
+	}
+
+	public StructuredDocumentEvent setText(final Object requester, final String theString) {
+		StructuredDocumentEvent event = null;
+		IExecutionDelegate executionDelegate = getExecutionDelegate();
+		if (executionDelegate == null) {
+			event = super.setText(requester, theString);
+		}
+		else {
+			final Object[] resultSlot = new Object[1];
+			JobSafeRunnable runnable = new JobSafeRunnable() {
+				public void run() throws Exception {
+					resultSlot[0] = JobSafeStructuredDocument.super.setText(requester, theString);
+				}
+				public void handleException(Throwable exception) {
+					resultSlot[0] = new NoChangeEvent(JobSafeStructuredDocument.this, requester, theString, 0, 0);
+					super.handleException(exception);
+				}
+			};
+			executionDelegate.execute(runnable);
+			event = (StructuredDocumentEvent) resultSlot[0];
+		}
+		return event;
+	}
+
+	public DocumentRewriteSession startRewriteSession(DocumentRewriteSessionType sessionType) throws IllegalStateException {
+		DocumentRewriteSession session = null;
+		IExecutionDelegate executionDelegate = getExecutionDelegate();
+		if (executionDelegate == null) {
+			session = internalStartRewriteSession(sessionType);
+		}
+		else {
+			final Object[] resultSlot = new Object[1];
+			final DocumentRewriteSessionType finalSessionType = sessionType;
+			JobSafeRunnable runnable = new JobSafeRunnable() {
+				public void run() throws Exception {
+					resultSlot[0] = internalStartRewriteSession(finalSessionType);
+				}
+			};
+			executionDelegate.execute(runnable);
+			if (resultSlot[0] instanceof Throwable) {
+				throw new RuntimeException((Throwable) resultSlot[0]);
+			}
+			else {
+				session = (DocumentRewriteSession) resultSlot[0];
+			}
+		}
+		return session;
+	}
+
+	public void stopRewriteSession(DocumentRewriteSession session) {
+		IExecutionDelegate executionDelegate = getExecutionDelegate();
+		if (executionDelegate == null) {
+			internalStopRewriteSession(session);
+		}
+		else {
+			final DocumentRewriteSession finalSession = session;
+			JobSafeRunnable runnable = new JobSafeRunnable() {
+				public void run() throws Exception {
+					internalStopRewriteSession(finalSession);
+				}
+			};
+			executionDelegate.execute(runnable);
+		}
+	}
+
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/MinimalDocument.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/MinimalDocument.java
new file mode 100644
index 0000000..de3ff23
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/MinimalDocument.java
@@ -0,0 +1,445 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.IDocumentPartitioningListener;
+import org.eclipse.jface.text.IPositionUpdater;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.TypedRegion;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.NotImplementedException;
+import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
+import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
+import org.eclipse.wst.sse.core.internal.provisional.events.IModelAboutToBeChangedListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextReParser;
+import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager;
+
+
+/**
+ * Purely a dummy "marker" instance for StructuredDocumentRegions which are
+ * created temorarily in the course of re-parsing. Primarily a place holder,
+ * but can be needed to get text from.
+ */
+public class MinimalDocument implements IStructuredDocument {
+	private SubSetTextStore data;
+
+	/**
+	 * Marked private to be sure never created without data being initialized.
+	 *  
+	 */
+	private MinimalDocument() {
+		super();
+	}
+
+	public MinimalDocument(SubSetTextStore initialContents) {
+		this();
+		data = initialContents;
+	}
+
+	public void addDocumentAboutToChangeListener(IModelAboutToBeChangedListener listener) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void addDocumentChangedListener(IStructuredDocumentListener listener) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void addDocumentChangingListener(IStructuredDocumentListener listener) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void addDocumentListener(IDocumentListener listener) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void addDocumentPartitioningListener(IDocumentPartitioningListener listener) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void addPosition(Position position) throws BadLocationException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void addPosition(String category, Position position) throws BadLocationException, BadPositionCategoryException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void addPositionCategory(String category) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void addPositionUpdater(IPositionUpdater updater) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void addPrenotifiedDocumentListener(IDocumentListener documentAdapter) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void clearReadOnly(int startOffset, int length) {
+		// TODO: this is called from notifier loop inappropriately
+		//	throw new NotImplementedException("intentionally not implemented");
+	}
+
+	public int computeIndexInCategory(String category, int offset) throws BadLocationException, BadPositionCategoryException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public int computeNumberOfLines(String text) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public ITypedRegion[] computePartitioning(int offset, int length) throws BadLocationException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public boolean containsPosition(String category, int offset, int length) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public boolean containsPositionCategory(String category) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public boolean containsReadOnly(int startOffset, int length) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void fireNewDocument(Object requester) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public String get() {
+		String result = null;
+		result = data.get(0, data.getLength());
+		return result;
+	}
+
+	public String get(int offset, int length) throws BadLocationException {
+		String result = null;
+		try {
+			result = data.get(offset, length);
+		} catch (StringIndexOutOfBoundsException e) {
+			throw new BadLocationException("offset: " + offset + " length: " + length + "\ndocument length: " + data.getLength());
+		}
+		return result;
+	}
+
+	public Object getAdapter(Class adapter) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public char getChar(int offset) throws BadLocationException {
+		return data.get(offset);
+	}
+
+	public String getContentType(int offset) throws BadLocationException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public IDocumentPartitioner getDocumentPartitioner() {
+		// temp fix
+		return null;
+		//		throw new NotImplementedException("intentionally not implemented");
+	}
+
+	public EncodingMemento getEncodingMemento() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public IStructuredDocumentRegion getFirstStructuredDocumentRegion() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public IStructuredDocumentRegion getLastStructuredDocumentRegion() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public String[] getLegalContentTypes() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public String[] getLegalLineDelimiters() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public int getLength() {
+		return data.getLength();
+	}
+
+	public String getPreferedLineDelimiter() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public String getLineDelimiter(int line) throws BadLocationException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public IRegion getLineInformation(int line) throws BadLocationException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public IRegion getLineInformationOfOffset(int offset) throws BadLocationException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public int getLineLength(int line) throws BadLocationException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public int getLineOffset(int line) throws BadLocationException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public int getLineOfOffset(int offset) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public int getNumberOfLines() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public int getNumberOfLines(int offset, int length) throws BadLocationException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public RegionParser getParser() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public ITypedRegion getPartition(int offset) throws BadLocationException {
+		Logger.log(Logger.WARNING, "An instance of MinimalDocument was asked for its partition, sometime indicating a deleted region was being accessed."); //$NON-NLS-1$
+		return new TypedRegion(0,0, "undefined"); //$NON-NLS-1$
+		//throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public String[] getPositionCategories() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public Position[] getPositions(String category) throws BadPositionCategoryException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public IPositionUpdater[] getPositionUpdaters() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public IStructuredDocumentRegion getRegionAtCharacterOffset(int offset) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public IStructuredDocumentRegionList getRegionList() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public IStructuredTextReParser getReParser() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public String getText() {
+		return data.get(0, data.getLength());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.text.IStructuredDocument#getUndoManager()
+	 */
+	public IStructuredTextUndoManager getUndoManager() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void insertPositionUpdater(IPositionUpdater updater, int index) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void makeReadOnly(int startOffset, int length) {
+		// TODO: this is called from notifier loop inappropriately
+		//	throw new NotImplementedException("intentionally not implemented");
+	}
+
+	public IStructuredDocument newInstance() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension#registerPostNotificationReplace(org.eclipse.jface.text.IDocumentListener,
+	 *      org.eclipse.jface.text.IDocumentExtension.IReplace)
+	 */
+	public void registerPostNotificationReplace(IDocumentListener owner, IReplace replace) throws UnsupportedOperationException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$		
+	}
+
+	public void removeDocumentAboutToChangeListener(IModelAboutToBeChangedListener listener) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void removeDocumentChangedListener(IStructuredDocumentListener listener) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void removeDocumentChangingListener(IStructuredDocumentListener listener) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void removeDocumentListener(IDocumentListener listener) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void removeDocumentPartitioningListener(IDocumentPartitioningListener listener) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void removePosition(Position position) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void removePosition(String category, Position position) throws BadPositionCategoryException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void removePositionCategory(String category) throws BadPositionCategoryException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void removePositionUpdater(IPositionUpdater updater) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void removePrenotifiedDocumentListener(IDocumentListener documentAdapter) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void replace(int offset, int length, String text) throws BadLocationException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+		//		data.replace(offset, length, text);
+	}
+
+	public StructuredDocumentEvent replaceText(Object source, int oldStart, int replacementLength, String requestedChange) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.text.IStructuredDocument#replaceText(java.lang.Object,
+	 *      int, int, java.lang.String, boolean)
+	 */
+	public StructuredDocumentEvent replaceText(Object source, int oldStart, int replacementLength, String requestedChange, boolean ignoreReadOnlySetting) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension#resumePostNotificationProcessing()
+	 */
+	public void resumePostNotificationProcessing() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public int search(int startOffset, String findString, boolean forwardSearch, boolean caseSensitive, boolean wholeWord) throws BadLocationException {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void set(String text) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+		//		data.set(text);
+	}
+
+	public void setDocumentPartitioner(IDocumentPartitioner partitioner) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void setEncodingMemento(EncodingMemento encodingMemento) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public void setPreferredLineDelimiter(String delimiter) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public StructuredDocumentEvent setText(Object requester, String allText) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.text.IStructuredDocument#setUndoManager(org.eclipse.wst.sse.core.undo.StructuredTextUndoManager)
+	 */
+	public void setUndoManager(IStructuredTextUndoManager undoManager) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension#startSequentialRewrite(boolean)
+	 */
+	public void startSequentialRewrite(boolean normalize) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension#stopPostNotificationProcessing()
+	 */
+	public void stopPostNotificationProcessing() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentExtension#stopSequentialRewrite()
+	 */
+	public void stopSequentialRewrite() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+
+	public String getLineDelimiter() {
+		return null;
+	}
+
+	public String getPreferredLineDelimiter() {
+		return null;
+	}
+
+	public void setLineDelimiter(String delimiter) {
+		
+	}
+	
+	public IStructuredDocumentRegion[] getStructuredDocumentRegions() {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+	
+	public IStructuredDocumentRegion[] getStructuredDocumentRegions(int start, int length) {
+		throw new NotImplementedException("intentionally not implemented"); //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/ReadOnlyPosition.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/ReadOnlyPosition.java
new file mode 100644
index 0000000..4c4bccf
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/ReadOnlyPosition.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+import org.eclipse.jface.text.Position;
+
+class ReadOnlyPosition extends Position {
+	private boolean fIncludeStartOffset = false;
+
+	public ReadOnlyPosition(int newOffset, int newLength, boolean includeStart) {
+		super(newOffset, newLength);
+		fIncludeStartOffset = includeStart;
+	}
+
+	public boolean overlapsWith(int newOffset, int newLength) {
+		boolean overlapsWith = super.overlapsWith(newOffset, newLength);
+		if (overlapsWith) {
+			/*
+			 * BUG157526 If at the start of the read only region and length =
+			 * 0 most likely asking to insert and want to all inserting before
+			 * read only region
+			 */
+			if (fIncludeStartOffset && (newLength == 0) && (this.length != 0) && (newOffset == this.offset)) {
+				overlapsWith = false;
+			}
+		}
+		return overlapsWith;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentReParser.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentReParser.java
new file mode 100644
index 0000000..1cad185
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentReParser.java
@@ -0,0 +1,1700 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2011 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (Intalio) - bug 300427 - Comparison of String Objects using == or !=
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.FindReplaceDocumentAdapter;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.ltk.parser.BlockTagParser;
+import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextReParser;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionCollection;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+
+
+/**
+ * This class provides a centralized place to put "reparsing" logic. This is
+ * the logic that reparses the text incrementally, as a user types in new
+ * characters, or DOM nodes are inserted or deleted. Note: it is not a thread
+ * safe class.
+ */
+public class StructuredDocumentReParser implements IStructuredTextReParser {
+	protected IStructuredDocumentRegion dirtyEnd = null;
+	protected IStructuredDocumentRegion dirtyStart = null;
+	final private String doubleQuote = new String(new char[]{'\"'});
+	protected final CoreNodeList EMPTY_LIST = new CoreNodeList();
+	protected String fChanges;
+	protected String fDeletedText;
+	protected boolean fIsEntireDocument;
+
+	private FindReplaceDocumentAdapter fFindReplaceDocumentAdapter = null;
+	protected int fLengthDifference;
+	protected int fLengthToReplace;
+	protected Object fRequester;
+	protected int fStart;
+	// note: this is the impl class of IStructuredDocument, not the interface
+	// FUTURE_TO_DO: I believe some of these can be made private now.?
+	protected BasicStructuredDocument fStructuredDocument;
+
+	/**
+	 * variable used in anticiapation of multithreading
+	 */
+	protected boolean isParsing;
+	final private String singleQuote = new String(new char[]{'\''});
+
+	public StructuredDocumentReParser() {
+		super();
+	}
+
+	public StructuredDocumentEvent _checkBlockNodeList(List blockTagList) {
+		StructuredDocumentEvent result = null;
+		if (blockTagList != null) {
+			for (int i = 0; i < blockTagList.size(); i++) {
+				org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker blockTag = (org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker) blockTagList.get(i);
+				String tagName = blockTag.getTagName();
+				final String tagStart = "<" + tagName; //$NON-NLS-1$
+				result = checkForCriticalName(tagStart); //$NON-NLS-1$
+				if (result != null)
+					break;
+				result = checkForCriticalName("</" + tagName); //$NON-NLS-1$
+				if (result != null)
+					break;
+				result = checkForSelfClosing(tagStart);
+				if (result != null)
+					break;
+				result = checkForTransitionToOpen(tagStart);
+				if (result != null)
+					break;
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Checks if the start region has become self-closing. e.g., &lt;style&gt; -&gt; &lt;style/&gt;
+	 */
+	private StructuredDocumentEvent checkForSelfClosing(String tagName) {
+		StructuredDocumentEvent result = null;
+		if (dirtyStart.getText().toLowerCase().indexOf(tagName.toLowerCase()) >= 0) { // within a start-tag
+			final int documentLength = fStructuredDocument.getLength();
+			int end = fStart + fLengthToReplace + fChanges.length() + 1;
+			if (end > documentLength)
+				end = documentLength - 1;
+			final String oldText = fStructuredDocument.get(fStart, 1);
+			final String peek = StringUtils.paste(oldText, fChanges, 0, fLengthToReplace);
+			if ("/>".equals(peek)) { // Reparse afterwards if the tag became self-closing
+				result = reparse(dirtyStart.getStart(), documentLength - 1);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Checks if the start region has become self-closing. e.g., &lt;style/&gt; -&gt; &lt;style&gt;
+	 */
+	private StructuredDocumentEvent checkForTransitionToOpen(String tagName) {
+		StructuredDocumentEvent result = null;
+		if (dirtyStart.getText().toLowerCase().indexOf(tagName.toLowerCase()) >= 0) { // within a start-tag
+			final int documentLength = fStructuredDocument.getLength();
+			int end = fStart + fLengthToReplace + fChanges.length() + 1;
+			if (end > documentLength)
+				end = documentLength - 1;
+			final String oldText = fStructuredDocument.get(fStart, 2);
+			final String peek = StringUtils.paste(oldText, fChanges, 0, fLengthToReplace);
+			if ("/>".equals(oldText) && ">".equals(peek)) { // Reparse afterwards if the block tag went from self-closing to open
+				result = reparse(dirtyStart.getStart(), documentLength - 1);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Common utility for checking for critical word such as " <SCRIPT>"
+	 */
+	private StructuredDocumentEvent _checkForCriticalWord(String criticalTarget, boolean checkEnd) {
+		StructuredDocumentEvent result = null;
+		int documentLength = fStructuredDocument.getLength();
+		int propLen = fLengthToReplace;
+		if (propLen > documentLength)
+			propLen = documentLength;
+		int startNeighborhood = fStart - criticalTarget.length();
+		int adjustInsert = 0;
+		if (startNeighborhood < 0) {
+			adjustInsert = 0 - startNeighborhood;
+			startNeighborhood = 0;
+		}
+		int endNeighborhood = fStart + fLengthToReplace + criticalTarget.length() - 1;
+		if (endNeighborhood > documentLength)
+			endNeighborhood = documentLength - 1;
+		int oldlen = endNeighborhood - startNeighborhood; // + 1;
+		if (oldlen + startNeighborhood > documentLength) {
+			oldlen = documentLength - startNeighborhood;
+		}
+		String oldText = fStructuredDocument.get(startNeighborhood, oldlen);
+		String peek = StringUtils.paste(oldText, fChanges, criticalTarget.length() - adjustInsert, fLengthToReplace);
+		boolean isCriticalString = checkTagNames(oldText, criticalTarget, checkEnd);
+		boolean toBeCriticalString = checkTagNames(peek, criticalTarget, checkEnd);
+		if ((isCriticalString != toBeCriticalString) || // OR if both are
+					// critical and there's
+					// a change in the end
+					// tag ('>')
+					((isCriticalString && toBeCriticalString) && (changeInIsEndedState(oldText, peek)))) {
+			// if it involves a change of a critical string (making one where
+			// there wasn't, or removing
+			// one where there was one) then reparse everthing.
+			result = reparse(0, documentLength - 1);
+		}
+		return result;
+	}
+
+	private int _computeStartOfDifferences(CoreNodeList oldNodes, CoreNodeList newNodes) {
+		int startOfDifferences = -1;
+		int newNodesLength = newNodes.getLength();
+		boolean foundDifference = false;
+		boolean done = false;
+		// we'll control our loop based on the old List length
+		int oldNodesLength = oldNodes.getLength();
+		// be sure to check 'done' first, so startOfDifferences isn't
+		// icremented if done is true
+		done : while ((!done) && (++startOfDifferences < oldNodesLength)) {
+			IStructuredDocumentRegion oldNode = oldNodes.item(startOfDifferences);
+			// this lessThanEffectedRegion is to check to be sure the node is
+			// infact a candidate
+			// to be considered as "old". This check is important for the case
+			// where some
+			// text is replaceing text that
+			// appears identical, but is a different instance. For example, if
+			// the text
+			// is <P><B></B></P> and <B></B> is inserted at postion 3,
+			// resulting in <P><B></B><B></B></P>
+			// we do not want the
+			// first <B> to be considered old ... it is the new one, the
+			// second
+			// <B> is the old one.
+			if (_lessThanEffectedRegion(oldNode)) {
+				// be sure to check that we have new nodes to compare against.
+				if (startOfDifferences > newNodesLength) {
+					foundDifference = false;
+					done = true;
+					continue done;
+				} else {
+					//
+					IStructuredDocumentRegion newNode = newNodes.item(startOfDifferences);
+					// note: shift is 0 while at beginning of list, before the
+					// insertion (or deletion) point. After that, it is
+					// fStart+fLengthDifference
+					if (!(oldNode.sameAs(newNode, 0))) {
+						foundDifference = true;
+						done = true;
+						continue done;
+					} else { // if they are equal, then we will be keeping the
+						// old one, so
+						// we need to be sure its parentDocument is set back
+						// to
+						// the right instance
+						oldNode.setParentDocument(fStructuredDocument);
+					}
+				}
+			} else {
+				// we didn't literally find a difference, but we count it as
+				// such by implication
+				foundDifference = true;
+				done = true;
+				continue done;
+			}
+		}
+		// if we literally found a difference, then all is ok and we can
+		// return
+		// it.
+		// if we did not literally find one, then we have to decide why.
+		if (!foundDifference) {
+			if (newNodesLength == oldNodesLength) { // then lists are
+				// identical
+				// (and may be of zero
+				// length)
+				startOfDifferences = -1;
+			} else {
+				if (newNodesLength > oldNodesLength) { // then lists are
+					// identical except for
+					// newNodes added
+					startOfDifferences = oldNodesLength;
+				} else {
+					if (newNodesLength < oldNodesLength) { // then lists are
+						// identical except
+						// for old Nodes
+						// deleted
+						startOfDifferences = newNodesLength;
+					}
+				}
+			}
+		}
+		return startOfDifferences;
+	}
+
+	private int _computeStartOfDifferences(IStructuredDocumentRegion oldNodeParam, ITextRegionList oldRegions, IStructuredDocumentRegion newNodeParam, ITextRegionList newRegions) {
+		int startOfDifferences = -1;
+		int newRegionsLength = newRegions.size();
+		boolean foundDifference = false;
+		boolean done = false;
+		// we'll control our loop based on the old List length
+		int oldRegionsLength = oldRegions.size();
+		// be sure to check 'done' first, so startOfDifferences isn't
+		// icremented if done is true
+		done : while ((!done) && (++startOfDifferences < oldRegionsLength)) {
+			ITextRegion oldRegion = oldRegions.get(startOfDifferences);
+			// this lessThanEffectedRegion is to check to be sure the node is
+			// infact a candidate
+			// to be considered as "old". This check is important for the case
+			// where some
+			// text is replaceing text that
+			// appears identical, but is a different instance. For example, if
+			// the text
+			// is <P><B></B></P> and <B></B> is inserted at postion 3,
+			// resulting in <P><B></B><B></B></P>
+			// we do not want the
+			// first <B> to be considered old ... it is the new one, the
+			// second
+			// <B> is the old one.
+			if (_lessThanEffectedRegion(oldNodeParam, oldRegion)) {
+				// be sure to check that we have new nodes to compare against.
+				if (startOfDifferences > newRegionsLength) {
+					foundDifference = false;
+					done = true;
+					continue done;
+				} else {
+					//
+					ITextRegion newRegion = newRegions.get(startOfDifferences);
+					// note: shift is 0 while at beginning of list, before the
+					// insertion (or deletion) point. After that, it is
+					// fStart+fLengthDifference
+					if (!(oldNodeParam.sameAs(oldRegion, newNodeParam, newRegion, 0))) {
+						foundDifference = true;
+						done = true;
+						continue done;
+					} else {
+						// if they are equal, then we will be keeping the old
+						// one.
+						// unlike the flatnode case, there is no reason to
+						// update
+						// the textstore, since its the same text store in
+						// either case
+						// (since its the same flatnode)
+						//oldRegion.setTextStore(fStructuredDocument.parentDocument);
+					}
+				}
+			} else {
+				// we didn't literally find a difference, but we count it as
+				// such by implication
+				foundDifference = true;
+				done = true;
+				continue done;
+			}
+		}
+		// if we literally found a difference, then all is ok and we can
+		// return
+		// it.
+		// if we did not literally find one, then we have to decide why.
+		if (!foundDifference) {
+			if (newRegionsLength == oldRegionsLength) { // then lists are
+				// identical (and may
+				// be of zero length)
+				startOfDifferences = -1;
+			} else {
+				if (newRegionsLength > oldRegionsLength) { // then lists are
+					// identical except
+					// for newRegions
+					// added
+					startOfDifferences = oldRegionsLength;
+				} else {
+					if (newRegionsLength < oldRegionsLength) { // then lists
+						// are identical
+						// except for
+						// old Nodes
+						// deleted
+						startOfDifferences = newRegionsLength;
+					}
+				}
+			}
+		}
+		return startOfDifferences;
+	}
+
+	/**
+	 * Part 1 of 2 steps to do a core_reparse
+	 * 
+	 * Parses a portion of the current text in the IStructuredDocument and
+	 * returns the raw result
+	 */
+	private IStructuredDocumentRegion _core_reparse_text(int rescanStart, int rescanEnd) {
+		fStructuredDocument.resetParser(rescanStart, rescanEnd);
+		return fStructuredDocument.getParser().getDocumentRegions();
+	}
+
+	/**
+	 * Part 2 of 2 steps to do a core_reparse
+	 * 
+	 * Integrates a list of StructuredDocumentRegions based on the current
+	 * text contents of the IStructuredDocument into the IStructuredDocument
+	 * data structure
+	 */
+	private StructuredDocumentEvent _core_reparse_update_model(IStructuredDocumentRegion newNodesHead, int rescanStart, int rescanEnd, CoreNodeList oldNodes, boolean firstTime) {
+		StructuredDocumentEvent result = null;
+		CoreNodeList newNodes = null;
+		// rescan
+		newNodes = new CoreNodeList(newNodesHead);
+		// adjust our newNode chain so the offset positions match
+		// our text store (not the simple string of text reparsed)
+		StructuredDocumentRegionIterator.adjustStart(newNodesHead, rescanStart);
+		// initialize the parentDocument variable of each instance in the new
+		// chain
+		StructuredDocumentRegionIterator.setParentDocument(newNodesHead, fStructuredDocument);
+		// initialize the structuredDocument variable of each instance in the
+		// new chain
+		//StructuredDocumentRegionIterator.setStructuredDocument(newNodesHead,
+		// fStructuredDocument);
+		//
+		if (firstTime) {
+			fStructuredDocument.setCachedDocumentRegion(newNodesHead);
+			fStructuredDocument.initializeFirstAndLastDocumentRegion();
+			// note: since we are inserting nodes, for the first time, there
+			// is
+			// no adjustments
+			// to downstream stuff necessary.
+			result = new StructuredDocumentRegionsReplacedEvent(fStructuredDocument, fRequester, oldNodes, newNodes, fChanges, fStart, fLengthToReplace, fIsEntireDocument);
+		} else {
+			// note: integrates changes into model as a side effect
+			result = minimumEvent(oldNodes, newNodes);
+		}
+		result.setDeletedText(fDeletedText);
+		return result;
+	}
+
+	private CoreNodeList _formMinimumList(CoreNodeList flatnodes, int startOfDifferences, int endOfDifferences) {
+		CoreNodeList minimalNodes = null;
+		// if startOfDifferces is still its initial value, then we have an
+		// empty document
+		if (startOfDifferences == -1) {
+			minimalNodes = EMPTY_LIST;
+		} else {
+			// if we do not have any flatnode in our flatnode list, then
+			// simply
+			// return our standard empty list
+			if (flatnodes.getLength() == 0) {
+				minimalNodes = EMPTY_LIST;
+			} else {
+				// if startOfDifferences is greater than endOfDifferences,
+				// then
+				// that means the calculations "crossed" each other, and
+				// hence,
+				// there really is no differences, so, again, return the empty
+				// list
+				if (startOfDifferences > endOfDifferences) {
+					minimalNodes = EMPTY_LIST;
+				} else {
+					// the last check be sure we have some differnces
+					if ((endOfDifferences > -1)) {
+						minimalNodes = new CoreNodeList(flatnodes.item(startOfDifferences), flatnodes.item(endOfDifferences));
+					} else {
+						// there were no differences, the list wasn't
+						// minimized, so simply return it.
+						minimalNodes = flatnodes;
+					}
+				}
+			}
+		}
+		return minimalNodes;
+	}
+
+	private boolean _greaterThanEffectedRegion(IStructuredDocumentRegion oldNode) {
+		boolean result = false;
+		int nodeStart = oldNode.getStartOffset();
+		int changedRegionEnd = fStart + fLengthToReplace - 1;
+		result = nodeStart > changedRegionEnd;
+		return result;
+	}
+
+	private boolean _greaterThanEffectedRegion(IStructuredDocumentRegion oldNode, ITextRegion oldRegion) {
+		boolean result = false;
+		int regionStartOffset = oldNode.getStartOffset(oldRegion);
+		int effectedRegionEnd = fStart + fLengthToReplace - 1;
+		result = regionStartOffset > effectedRegionEnd;
+		return result;
+	}
+
+	private boolean _lessThanEffectedRegion(IStructuredDocumentRegion oldNode) {
+		boolean result = false;
+		int nodeEnd = oldNode.getEndOffset() - 1;
+		result = nodeEnd < fStart;
+		return result;
+	}
+
+	private boolean _lessThanEffectedRegion(IStructuredDocumentRegion oldNode, ITextRegion oldRegion) {
+		boolean result = false;
+		int nodeEnd = oldNode.getEndOffset(oldRegion) - 1;
+		result = nodeEnd < fStart;
+		return result;
+	}
+
+	private boolean _regionsSameKind(ITextRegion newRegion, ITextRegion oldRegion) {
+		boolean result = false;
+		// if one region is a container region, and the other not, always
+		// return false
+		// else, just check their type.
+		//      DW druing refactoring, looks like a "typo" here, using 'old' in
+		// both.
+		//		if (isContainerRegion(oldRegion) != isContainerRegion(oldRegion))
+		if (isCollectionRegion(oldRegion) != isCollectionRegion(newRegion))
+			result = false;
+		else if (oldRegion.getType().equals(newRegion.getType()))
+			result = true;
+		return result;
+	}
+
+	//	private boolean hasCollectionRegions(ITextRegion aRegion) {
+	//		boolean result = false;
+	//		if (aRegion instanceof ITextRegionCollection) {
+	//			ITextRegionCollection regionContainter = (ITextRegionCollection)
+	// aRegion;
+	//			ITextRegionList regions = regionContainter.getRegions();
+	//			Iterator iterator = regions.iterator();
+	//			while (iterator.hasNext()) {
+	//				if (aRegion instanceof ITextRegionCollection) {
+	//					result = true;
+	//					break;
+	//				}
+	//			}
+	//		}
+	//		return result;
+	//	}
+	/**
+	 * This method is specifically to detect changes in 'isEnded' state,
+	 * although it still does so with heuristics. If number of '>' changes,
+	 * assume the isEnded state has changed.
+	 */
+	private boolean changeInIsEndedState(String oldText, String newText) {
+		int nOld = StringUtils.occurrencesOf(oldText, '>');
+		int nNew = StringUtils.occurrencesOf(newText, '>');
+		return !(nOld == nNew);
+	}
+
+	private void checkAndAssignParent(IStructuredDocumentRegion oldNode, ITextRegion region) {
+		if (region instanceof ITextRegionContainer) {
+			((ITextRegionContainer) region).setParent(oldNode);
+			return;
+		}
+		if (region instanceof ITextRegionCollection) {
+			ITextRegionCollection textRegionCollection = (ITextRegionCollection) region;
+			ITextRegionList regionList = textRegionCollection.getRegions();
+			for (int i = 0; i < regionList.size(); i++) {
+				ITextRegion innerRegion = regionList.get(i);
+				checkAndAssignParent(oldNode, innerRegion);
+			}
+		}
+	}
+
+	/**
+	 * A change to a CDATA tag can result in all being reparsed.
+	 */
+	private StructuredDocumentEvent checkForCDATA() {
+		StructuredDocumentEvent result = null;
+		result = checkForCriticalKey("<![CDATA["); //$NON-NLS-1$
+		if (result == null)
+			result = checkForCriticalKey("]]>"); //$NON-NLS-1$
+		return result;
+	}
+
+	/**
+	 * If a comment start or end tag is being added or deleted, we'll rescan
+	 * the whole document. The reason is that content that is revealed or
+	 * commented out can effect the interpretation of the rest of the
+	 * document. Note: for now this is very XML specific, can refactor/improve
+	 * later.
+	 */
+	protected StructuredDocumentEvent checkForComments() {
+		StructuredDocumentEvent result = null;
+		result = checkForCriticalKey("<!--"); //$NON-NLS-1$
+		if (result == null)
+			result = checkForCriticalKey("-->"); //$NON-NLS-1$
+		// we'll also check for these degenerate cases
+		if (result == null)
+			result = checkForCriticalKey("<!--->"); //$NON-NLS-1$
+		return result;
+	}
+
+	/**
+	 * Common utility for checking for critical word such as " <SCRIPT>"
+	 */
+	protected StructuredDocumentEvent checkForCriticalKey(String criticalTarget) {
+		return _checkForCriticalWord(criticalTarget, false);
+	}
+
+	/**
+	 * Common utility for checking for critical word such as " <SCRIPT>"
+	 */
+	private StructuredDocumentEvent checkForCriticalName(String criticalTarget) {
+		return _checkForCriticalWord(criticalTarget, true);
+	}
+
+	//	/**
+	//	 * Currently this method is pretty specific to ?ML
+	//	 * @deprecated - not really deprecated, but plan to make
+	//	 * protected ... I'm not sure why its public or misspelled?
+	//	 */
+	protected StructuredDocumentEvent checkForCrossStructuredDocumentRegionBoundryCases() {
+		StructuredDocumentEvent result = null;
+		// Case 1: See if the language's syntax requires that multiple
+		// StructuredDocumentRegions be rescanned
+		if (result == null) {
+			result = checkForCrossStructuredDocumentRegionSyntax();
+		}
+		// Case 2: "block tags" whose content is left unparsed
+		if (result == null) {
+			Object parser = fStructuredDocument.getParser();
+			if (parser instanceof BlockTagParser) {
+				List blockTags = ((BlockTagParser) parser).getBlockMarkers();
+				result = _checkBlockNodeList(blockTags);
+			}
+		}
+		// FUTURE_TO_DO: is there a better place to do this?
+		// or! do we already do it some other more central place?
+		if (result != null) {
+			result.setDeletedText(fDeletedText);
+		}
+		return result;
+	}
+
+	/**
+	 * Allow a reparser to check for extra syntactic cases that require
+	 * parsing beyond the flatNode boundary.
+	 * 
+	 * This implementation is very XML-centric.
+	 */
+	protected StructuredDocumentEvent checkForCrossStructuredDocumentRegionSyntax() {
+		StructuredDocumentEvent result;
+		// Case 1: Quote characters are involved
+		result = checkForQuotes();
+		if (result == null) {
+			// Case 2: The input forms or undoes a comment beginning or
+			// comment
+			// end
+			result = checkForComments();
+		}
+		if (result == null) {
+			// Case 3: The input forms or undoes a processing instruction
+			result = checkForPI();
+		}
+		if (result == null) {
+			// Case 4: The input forms or undoes a CDATA section
+			result = checkForCDATA();
+		}
+		return result;
+	}
+
+	/**
+	 * Checks to see if change request exactly matches the text it would be
+	 * replacing. (In future, this, or similar method is where to check for
+	 * "read only" attempted change.)
+	 */
+	private StructuredDocumentEvent checkForNoChange() {
+		StructuredDocumentEvent result = null;
+		// don't check equals unless lengths match
+		// should be a tiny bit faster, since usually not
+		// of equal lengths (I'm surprised String's equals method
+		// doesn't do this.)
+		if ((fChanges != null) && (fDeletedText != null) && (fChanges.length() == fDeletedText.length()) && (fChanges.equals(fDeletedText))) {
+			result = new NoChangeEvent(fStructuredDocument, fRequester, fChanges, fStart, fLengthToReplace);
+			((NoChangeEvent)result).reason = NoChangeEvent.NO_CONTENT_CHANGE;
+		}
+		return result;
+	}
+
+	/**
+	 * A change to a PI tag can result in all being reparsed.
+	 */
+	private StructuredDocumentEvent checkForPI() {
+		StructuredDocumentEvent result = null;
+		result = checkForCriticalKey("<?"); //$NON-NLS-1$
+		if (result == null)
+			result = checkForCriticalKey("?>"); //$NON-NLS-1$
+		return result;
+	}
+
+	/*
+	 * For simplicity, if either text to be deleted, or text to be inserted
+	 * contains at least one quote, we'll search for previous quote in
+	 * document, if any, and use that document region as a dirty start, and we'll use
+	 * end of document as dirty end. We need to assume either \" or \' is an
+	 * acceptable quote. (NOTE: this is, loosely, an XML assumption -- other
+	 * languages would differ, but we'll "hard code" for XML for now.
+	 * 
+	 * future_TODO: this is a really bad heuristic ... we should be looking
+	 * for odd number of quotes within a structuredDocumentRegion (or
+	 * something!) This causes way too much reparsing on simple cases, like
+	 * deleting a tag with a quoted attribute!
+	 */
+	private StructuredDocumentEvent checkForQuotes() {
+		// routine is supported with null or empty string meaning the same
+		// thing: deletion
+		if (fChanges == null)
+			fChanges = ""; //$NON-NLS-1$
+		//
+		StructuredDocumentEvent result = null;
+		try {
+			int dirtyStartPos = -1;
+			String proposedDeletion = fStructuredDocument.get(fStart, fLengthToReplace);
+			if (fStart < fStructuredDocument.getLength()) {
+				if ((fChanges.indexOf(singleQuote) > -1) || (proposedDeletion.indexOf(singleQuote) > -1)) {
+					IRegion singleQuoteRegion = getFindReplaceDocumentAdapter().find(fStart, singleQuote, false, false, false, false);
+					if (singleQuoteRegion != null) {
+						dirtyStartPos = singleQuoteRegion.getOffset();
+					}
+				} else if ((fChanges.indexOf(doubleQuote) > -1) || (proposedDeletion.indexOf(doubleQuote) > -1)) {
+					IRegion doubleQuoteRegion = getFindReplaceDocumentAdapter().find(fStart, doubleQuote, false, false, false, false);
+					if (doubleQuoteRegion != null) {
+						dirtyStartPos = doubleQuoteRegion.getOffset();
+					}
+				}
+			}
+			if (dirtyStartPos > -1) {
+				// then we found one, do create new structuredDocument event
+				// based on the previous quote to end of document
+				// except, we need to be positive that the previous quote is
+				// in a "safe start" region (e.g. if in JSP content, we need
+				// to
+				// backup till we include the whole JSP region, in order for
+				// it
+				// to be correctly re-parsed. The backing up is done in the
+				// reparse/find dirty start from hint
+				// method.
+				result = reparse(dirtyStartPos, fStructuredDocument.getLength() - 1);
+			}
+		} catch (BadLocationException e) {
+			Logger.logException(e);
+		}
+		if (result != null) {
+			result.setDeletedText(fDeletedText);
+		}
+		return result;
+	}
+
+	private StructuredDocumentEvent checkHeuristics() {
+		StructuredDocumentEvent result = null;
+		result = checkForNoChange();
+		if (result == null) {
+			result = checkForCrossStructuredDocumentRegionBoundryCases();
+			if (result == null) {
+				result = quickCheck();
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Takes into account "tag name" rules for comparisons; case-insensitive.
+	 */
+	private boolean checkTagNames(String compareText, String criticalTarget, boolean checkEnd) {
+		boolean result = false;
+		if ((compareText == null) || (criticalTarget == null))
+			return false;
+		int posOfCriticalWord = compareText.toLowerCase().indexOf(criticalTarget.toLowerCase());
+		result = posOfCriticalWord > -1;
+		if (checkEnd && result) {
+			// instead of returning true right away, we'll only return true
+			// the
+			// potentially matched tag is indeed a tag, for example, if
+			// <SCRIPT
+			// becomes <SCRIPTS we don't want to say the latter is a critical
+			// tag
+			int lastPos = posOfCriticalWord + criticalTarget.length();
+			if (lastPos < compareText.length()) {
+				char lastChar = compareText.charAt(lastPos);
+				// Future: check formal definition of this java method, vs.
+				// XML
+				// parsing rules
+				result = (!Character.isLetterOrDigit(lastChar));
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * The core reparsing method ... after the dirty start and dirty end have
+	 * been calculated elsewhere, and the text updated.
+	 */
+	protected StructuredDocumentEvent core_reparse(int rescanStart, int rescanEnd, CoreNodeList oldNodes, boolean firstTime) {
+		IStructuredDocumentRegion newNodesHead = null;
+		StructuredDocumentEvent result = null;
+		newNodesHead = _core_reparse_text(rescanStart, rescanEnd);
+		result = _core_reparse_update_model(newNodesHead, rescanStart, rescanEnd, oldNodes, firstTime);
+		return result;
+	}
+
+	/**
+	 * Resets state to "not parsing"
+	 */
+	private synchronized void endReParse() {
+		isParsing = false;
+		dirtyStart = null;
+		dirtyEnd = null;
+		fChanges = null;
+		fDeletedText = null;
+		fIsEntireDocument = false;
+	}
+
+	protected IStructuredDocumentRegion findDirtyEnd(int end) {
+		// Caution: here's one place we have to cast
+		IStructuredDocumentRegion result = fStructuredDocument.getRegionAtCharacterOffset(end);
+		// if not well formed, get one past, if there is something there
+		if ((result != null) && (!result.isEnded())) {
+			if (result.getNext() != null) {
+				result = result.getNext();
+			}
+		}
+		// also, get one past if exactly equal to the end (this was needed
+		// as a simple fix to when a whole exact region is deleted.
+		// there's probably a better way.
+		if ((result != null) && (end == result.getEnd())) {
+			if (result.getNext() != null) {
+				result = result.getNext();
+			}
+		}
+		// moved to subclass for quick transition
+		// 12/6/2001 - Since we've changed the parser/scanner to allow a lone
+		// '<' without
+		// always interpretting it as start of a tag name, we need to be a
+		// little fancier, in order
+		// to "skip" over any plain 'ol content between the lone '<' and any
+		// potential meating
+		// regions past plain 'ol content.
+		//		if (isLoneOpenFollowedByContent(result) && (result.getNext() !=
+		// null)) {
+		//			result = result.getNext();
+		//		}
+		if (result != null)
+			fStructuredDocument.setCachedDocumentRegion(result);
+		dirtyEnd = result;
+		return dirtyEnd;
+	}
+
+	protected void findDirtyStart(int start) {
+		IStructuredDocumentRegion result = fStructuredDocument.getRegionAtCharacterOffset(start);
+		// heuristic: if the postion is exactly equal to the start, then
+		// go back one more, if it exists. This prevents problems with
+		// insertions
+		// of text that should be merged with the previous node instead of
+		// simply hung
+		// off of it as a separate node (ex.: XML content inserted right
+		// before
+		// an open
+		// bracket should become part of the previous content node)
+		if (result != null) {
+			IStructuredDocumentRegion previous = result.getPrevious();
+			if ((previous != null) && ((!(previous.isEnded())) || (start == result.getStart()))) {
+				result = previous;
+			}
+			// If we are now at the end of a "tag dependent" content area (or
+			// JSP area)
+			// then we need to back up all the way to the beginning of that.
+			IStructuredDocumentRegion potential = result;
+			// moved to subclass to speed transition
+			//			while (isPartOfBlockRegion(potential)) {
+			//				potential = potential.getPrevious();
+			//			}
+			if (potential != null) {
+				result = potential;
+				fStructuredDocument.setCachedDocumentRegion(result);
+			}
+		}
+		dirtyStart = result;
+	}
+
+	protected CoreNodeList formOldNodes(IStructuredDocumentRegion dirtyStart, IStructuredDocumentRegion dirtyEnd) {
+		CoreNodeList oldNodes = new CoreNodeList(dirtyStart, dirtyEnd);
+		// Now save the old text, that "goes with" the old nodes and regions.
+		// Notice we are getting it directly from the text store
+		String oldText = null;
+		int oldStart = -1;
+		int oldEnd = -1;
+		// make sure there is some text, if not, use empty string
+		// (if one node is not null, the other should ALWAYS be not null too,
+		// since it
+		// would at least be equal to it.)
+		if (dirtyStart != null) {
+			oldStart = dirtyStart.getStart();
+			oldEnd = dirtyEnd.getEnd();
+			oldText = fStructuredDocument.get(oldStart, oldEnd - oldStart);
+		} else {
+			oldStart = 0;
+			oldEnd = 0;
+			oldText = ""; //$NON-NLS-1$
+		}
+		// create a temporary text store for this text
+		SubSetTextStore subTextStore = new SubSetTextStore(oldText, oldStart, oldEnd, fStructuredDocument.getLength());
+		// Now update the text store of the oldNodes
+		StructuredDocumentRegionIterator.setParentDocument(oldNodes, new MinimalDocument(subTextStore));
+		return oldNodes;
+	}
+
+	/**
+	 * @return Returns the findReplaceDocumentAdapter.
+	 */
+	public FindReplaceDocumentAdapter getFindReplaceDocumentAdapter() {
+		if (fFindReplaceDocumentAdapter == null) {
+			fFindReplaceDocumentAdapter = new FindReplaceDocumentAdapter(fStructuredDocument);
+		}
+		return fFindReplaceDocumentAdapter;
+	}
+
+	// Note: if thead safety is needed, this and all the other public methods
+	// of this class
+	// should be synchronized.
+	public void initialize(Object requester, int start, int lengthToReplace, String changes) {
+		isParsing = true;
+		fRequester = requester;
+		fStart = start;
+		fLengthToReplace = lengthToReplace;
+		fChanges = changes;
+		// notice this one is derived
+		fLengthDifference = Utilities.calculateLengthDifference(fChanges, fLengthToReplace);
+		fDeletedText = fStructuredDocument.get(fStart, fLengthToReplace);
+		int docLength = fStructuredDocument.getLength();
+		fIsEntireDocument = lengthToReplace >= docLength && docLength > 0;
+	}
+
+	protected void insertNodes(IStructuredDocumentRegion previousOldNode, IStructuredDocumentRegion nextOldNode, CoreNodeList newNodes) {
+		//
+		IStructuredDocumentRegion firstNew = null;
+		IStructuredDocumentRegion lastNew = null;
+		//
+		IStructuredDocumentRegion oldPrevious = previousOldNode;
+		IStructuredDocumentRegion oldNext = nextOldNode;
+		//
+		if (newNodes.getLength() > 0) {
+			// get pointers
+			firstNew = newNodes.item(0);
+			lastNew = newNodes.item(newNodes.getLength() - 1);
+			// switch surrounding StructuredDocumentRegions' references to
+			// lists
+			if (oldPrevious != null)
+				oldPrevious.setNext(firstNew);
+			if (oldNext != null) {
+				oldNext.setPrevious(lastNew);
+			} else {
+				// SIDE EFFECT
+				// if oldNext is null, that means we are replaceing the
+				// lastNode in the chain,
+				// so we need to update the structuredDocuments lastNode as
+				// the
+				// last of the new nodes.
+				fStructuredDocument.setLastDocumentRegion(newNodes.item(newNodes.getLength() - 1));
+			}
+			if (firstNew != null)
+				firstNew.setPrevious(oldPrevious);
+			if (lastNew != null)
+				lastNew.setNext(oldNext);
+		}
+		// else nothing to insert
+	}
+
+	/**
+	 * @param oldRegion
+	 */
+	private boolean isCollectionRegion(ITextRegion aRegion) {
+		return (aRegion instanceof ITextRegionCollection);
+	}
+
+	/**
+	 * @return boolean
+	 */
+	public boolean isParsing() {
+		return isParsing;
+	}
+
+	/**
+	 * The minimization algorithm simply checks the old nodes to see if any of
+	 * them "survived" the rescan and are unchanged. If so, the instance of
+	 * the old node is used instead of the new node. Before the requested
+	 * change, need to check type, offsets, and text to determine if the same.
+	 * After the requested change, need to check type and text, but adjust the
+	 * offsets to what ever the change was.
+	 */
+	protected StructuredDocumentEvent minimumEvent(CoreNodeList oldNodes, CoreNodeList newNodes) {
+		StructuredDocumentEvent event = null;
+		CoreNodeList minimalOldNodes = null;
+		CoreNodeList minimalNewNodes = null;
+		// To minimize nodes, we'll collect all those
+		// that are not equal into old and new lists
+		// Note: we assume that old and new nodes
+		// are basically contiguous -- and we force it to be so,
+		// by starting at the beginning to
+		// find first difference, and then starting at the end to find
+		// last difference. Everything in between we assume is different.
+		//
+		//
+		//
+		// startOfDifferences is the index into the core node list where the
+		// first difference
+		// occurs. But it may point into the old or the new list.
+		int startOfDifferences = _computeStartOfDifferences(oldNodes, newNodes);
+		int endOfDifferencesOld = -1;
+		int endOfDifferencesNew = -1;
+		// if one of the lists are shorter than where the differences start,
+		// then
+		// then some portion of the lists are identical
+		if ((startOfDifferences >= oldNodes.getLength()) || (startOfDifferences >= newNodes.getLength())) {
+			if (oldNodes.getLength() < newNodes.getLength()) {
+				// Then there are new regions to add
+				//     these lengths will cause the vector of old ones to not
+				//     have any elements, and the vector of new regions to have
+				//     just the new ones not in common with the old ones
+				//startOfDifferences should equal oldNodes.getLength(),
+				// calculated above on _computeStartOfDifferences
+				minimalOldNodes = EMPTY_LIST;
+				endOfDifferencesNew = newNodes.getLength() - 1;
+				minimalNewNodes = _formMinimumList(newNodes, startOfDifferences, endOfDifferencesNew);
+			} else {
+				if (oldNodes.getLength() > newNodes.getLength()) {
+					// delete old
+					// then there are old regions to delete
+					//    these lengths will cause the vector of old regions to
+					//    contain the ones to delete, and the vector of new
+					// regions
+					//    not have any elements
+					//startOfDifferences should equal newNodes.getLength(),
+					// calculated above on _computeStartOfDifferences
+					endOfDifferencesOld = oldNodes.getLength() - 1;
+					minimalOldNodes = _formMinimumList(oldNodes, startOfDifferences, endOfDifferencesOld);
+					minimalNewNodes = EMPTY_LIST;
+				} else
+					// unlikely event
+					event = new NoChangeEvent(fStructuredDocument, fRequester, fChanges, fStart, fLengthToReplace);
+			}
+		} else {
+			// We found a normal startOfDiffernces, but have not yet found the
+			// ends.
+			// We'll look for the end of differences by going backwards down
+			// the two lists.
+			// Here we need a seperate index for each array, since they may be
+			// (and
+			// probably are) of different lengths.
+			int indexOld = oldNodes.getLength() - 1;
+			int indexNew = newNodes.getLength() - 1;
+			// The greaterThanEffectedRegion is important to gaurd against
+			// incorrect counting
+			// when something identical is inserted to what's already there
+			// (see minimization test case 5)
+			// Note: the indexOld > startOfDifferences keeps indexOld from
+			// getting too small,
+			// so that the subsequent oldNodes.item(indexOld) is always valid.
+			while ((indexOld >= startOfDifferences) && (_greaterThanEffectedRegion(oldNodes.item(indexOld)))) {
+				if (!(oldNodes.item(indexOld).sameAs(newNodes.item(indexNew), fLengthDifference))) {
+					break;
+				} else {
+					// if they are equal, then we will be keeping the old one,
+					// so
+					// we need to be sure its parentDocument is set back to
+					// the
+					// right instance
+					oldNodes.item(indexOld).setParentDocument(fStructuredDocument);
+				}
+				indexOld--;
+				indexNew--;
+			}
+			endOfDifferencesOld = indexOld;
+			endOfDifferencesNew = indexNew;
+			minimalOldNodes = _formMinimumList(oldNodes, startOfDifferences, endOfDifferencesOld);
+			minimalNewNodes = _formMinimumList(newNodes, startOfDifferences, endOfDifferencesNew);
+		} /////////////////////////////////////////
+		//
+		IStructuredDocumentRegion firstDownStreamNode = null;
+		event = regionCheck(minimalOldNodes, minimalNewNodes);
+		if (event != null) {
+			firstDownStreamNode = minimalOldNodes.item(0).getNext();
+			if (firstDownStreamNode != null && fLengthDifference != 0) { // if
+				// firstDownStream
+				// is
+				// null,
+				// then
+				// we're
+				// at
+				// the
+				// end
+				// of
+				// the
+				// document
+				StructuredDocumentRegionIterator.adjustStart(firstDownStreamNode, fLengthDifference);
+			} //
+		} else {
+			event = nodesReplacedCheck(minimalOldNodes, minimalNewNodes);
+			// now splice the new chain of nodes to where the old chain is (or
+			// was)
+			// the firstDownStreamNode (the first of those after the new
+			// nodes)
+			// is
+			// remembered as a tiny optimization.
+			if (minimalOldNodes.getLength() == 0 && minimalNewNodes.getLength() > 0) {
+				// if no old nodes are being deleted, then use the
+				// the newNodes offset (minus one) to find the point to
+				// update downstream nodes, and after updating downstream
+				// nodes postions, insert the new ones.
+				int insertOffset = minimalNewNodes.item(0).getStartOffset();
+				IStructuredDocumentRegion lastOldUnchangedNode = null;
+				if (insertOffset > 0) {
+					lastOldUnchangedNode = fStructuredDocument.getRegionAtCharacterOffset(insertOffset - 1);
+					firstDownStreamNode = lastOldUnchangedNode.getNext();
+				} else {
+					// we're inserting at very beginning
+					firstDownStreamNode = fStructuredDocument.getFirstStructuredDocumentRegion();
+					// SIDE EFFECT: change the firstNode pointer if we're
+					// inserting at beginning
+					fStructuredDocument.setFirstDocumentRegion(minimalNewNodes.item(0));
+				}
+				StructuredDocumentRegionIterator.adjustStart(firstDownStreamNode, fLengthDifference);
+				insertNodes(lastOldUnchangedNode, firstDownStreamNode, minimalNewNodes);
+				// this (nodes replaced) is the only case where we need to
+				// update the cached Node
+				reSetCachedNode(minimalOldNodes, minimalNewNodes);
+			} else {
+				firstDownStreamNode = switchNodeLists(minimalOldNodes, minimalNewNodes);
+				// no need to adjust the length of the new nodes themselves,
+				// they
+				// are already correct, but we do need to
+				// adjust all "down stream" nodes with the length of the
+				// insertion or deletion
+				// --- adjustment moved to calling method.
+				if (firstDownStreamNode != null) {
+					// && event != null
+					StructuredDocumentRegionIterator.adjustStart(firstDownStreamNode, fLengthDifference);
+				} //
+				// this (nodes replaced) is the only case where we need to
+				// update the cached Node
+				reSetCachedNode(minimalOldNodes, minimalNewNodes);
+			}
+		}
+		return event;
+	}
+
+	// TODO: This should be abstract.
+	public IStructuredTextReParser newInstance() {
+		return new StructuredDocumentReParser();
+	}
+
+	protected StructuredDocumentEvent nodesReplacedCheck(CoreNodeList oldNodes, CoreNodeList newNodes) {
+		// actually, nothing to check here, since (and assuming) we've already
+		// minimized the number of nodes, and ruled out mere region changes
+		StructuredDocumentEvent result = new StructuredDocumentRegionsReplacedEvent(fStructuredDocument, fRequester, oldNodes, newNodes, fChanges, fStart, fLengthToReplace, fIsEntireDocument);
+		return result;
+	}
+
+	/**
+	 * A method to allow any heuristic "quick checks" that might cover many
+	 * many cases, before expending the time on a full reparse.
+	 *  
+	 */
+	public StructuredDocumentEvent quickCheck() {
+		StructuredDocumentEvent result = null;
+		// if the dirty start is null, then we have an empty document.
+		// in which case we'll return null so everything can be
+		// reparsed "from scratch" . If its not null, we'll give the flatnode
+		// a
+		// chance
+		// to handle, but only if there is one flatnode involved.
+		if (dirtyStart != null && dirtyStart == dirtyEnd) {
+			IStructuredDocumentRegion targetNode = dirtyStart;
+			result = dirtyStart.updateRegion(fRequester, targetNode, fChanges, fStart, fLengthToReplace);
+			if (result != null) {
+				// at this point only, we need to update the text store and
+				// and downstream nodes.
+				// FUTURE_TO_DO: can this dependency on structuredDocument
+				// method be eliminated?
+				fStructuredDocument.updateDocumentData(fStart, fLengthToReplace, fChanges);
+				IStructuredDocumentRegion firstDownStreamNode = targetNode.getNext();
+				// then flatnode must have been the last one, so need to
+				// update
+				// any downstream ones
+				if (firstDownStreamNode != null) {
+					StructuredDocumentRegionIterator.adjustStart(firstDownStreamNode, fLengthDifference);
+				}
+			}
+		}
+		if (result != null) {
+			result.setDeletedText(fDeletedText);
+		}
+		return result;
+	}
+
+	/**
+	 * If only one node is involved, sees how many regions are changed. If
+	 * only one, then its a 'regionChanged' event ... if more than one, its a
+	 * 'regionsReplaced' event.
+	 */
+	protected StructuredDocumentEvent regionCheck(CoreNodeList oldNodes, CoreNodeList newNodes) {
+		if (Debug.debugStructuredDocument)
+			System.out.println("IStructuredDocument::regionsReplacedCheck"); //$NON-NLS-1$
+		//$NON-NLS-1$
+		//$NON-NLS-1$
+		// the "regionsReplaced" event could only be true if and only if the
+		// nodelists
+		// are each only "1" in length.
+		StructuredDocumentEvent result = null;
+		int oldLength = oldNodes.getLength();
+		int newLength = newNodes.getLength();
+		if ((oldLength != 1) || (newLength != 1)) {
+			result = null;
+		} else {
+			IStructuredDocumentRegion oldNode = oldNodes.item(0);
+			IStructuredDocumentRegion newNode = newNodes.item(0);
+			result = regionCheck(oldNode, newNode);
+		}
+		return result;
+	}
+
+	/**
+	 * If only one node is involved, sees how many regions are changed. If
+	 * only one, then its a 'regionChanged' event ... if more than one, its a
+	 * 'regionsReplaced' event.
+	 */
+	protected StructuredDocumentEvent regionCheck(IStructuredDocumentRegion oldNode, IStructuredDocumentRegion newNode) {
+		//
+		StructuredDocumentEvent result = null;
+		ITextRegionList oldRegions = oldNode.getRegions();
+		ITextRegionList newRegions = newNode.getRegions();
+		ITextRegion[] oldRegionsArray = oldRegions.toArray();
+		ITextRegion[] newRegionsArray = newRegions.toArray();
+		//
+		// for the 'regionsReplaced' event, we don't care if
+		// the regions changed due to type, or text,
+		// we'll just collect all those that are not equal
+		// into the old and new region lists.
+		// Note: we, of course, assume that old and new regions
+		// are basically contiguous -- and we force it to be so,
+		// even if not literally so, by starting at beginning to
+		// find first difference, and then starting at end to find
+		// last difference. Everything in between we assume is different.
+		//
+		// going up is easy, we start at zero in each, and continue
+		// till regions are not the same.
+		int startOfDifferences = _computeStartOfDifferences(oldNode, oldRegions, newNode, newRegions);
+		int endOfDifferencesOld = -1;
+		int endOfDifferencesNew = -1;
+		//
+		//
+		// if one of the lists are shorter than where the differences start,
+		// then
+		// then some portion of the lists are identical
+		if ((startOfDifferences >= oldRegions.size()) || (startOfDifferences >= newRegions.size())) {
+			if (oldRegions.size() < newRegions.size()) {
+				// INSERT CASE
+				// then there are new regions to add
+				//     these lengths will cause the vector of old ones to not
+				//     have any elements, and the vector of new regions to have
+				//     just the new ones.
+				startOfDifferences = oldRegionsArray.length;
+				endOfDifferencesOld = oldRegionsArray.length - 1;
+				endOfDifferencesNew = newRegionsArray.length - 1;
+			} else {
+				if (oldRegions.size() > newRegions.size()) {
+					// DELETE CASE
+					// then there are old regions to delete
+					//    these lengths will cause the vector of old regions to
+					//    contain the ones to delete, and the vector of new
+					// regions
+					//    not have any elements
+					startOfDifferences = newRegionsArray.length;
+					endOfDifferencesOld = oldRegionsArray.length - 1;
+					endOfDifferencesNew = newRegionsArray.length - 1;
+				} else {
+					// else the lists are identical!
+					// unlikely event, probably error in current design, since
+					// we check for identity at the very beginning of
+					// reparsing.
+					result = new NoChangeEvent(fStructuredDocument, fRequester, fChanges, fStart, fLengthToReplace);
+				}
+			}
+		} else {
+			if ((startOfDifferences > -1) && (endOfDifferencesOld < 0) && (endOfDifferencesNew < 0)) {
+				// We found a normal startOfDiffernces, but have not yet found
+				// the ends.
+				// We'll look for the end of differences by going backwards
+				// down the two lists.
+				// Here we need a seperate index for each array, since they
+				// may
+				// be (and
+				// probably are) of different lengths.
+				int indexOld = oldRegionsArray.length - 1;
+				int indexNew = newRegionsArray.length - 1;
+				while ((indexOld >= startOfDifferences) && (_greaterThanEffectedRegion(oldNode, oldRegionsArray[indexOld]))) {
+					if ((!(oldNode.sameAs(oldRegionsArray[indexOld], newNode, newRegionsArray[indexNew], fLengthDifference)))) {
+						//endOfDifferencesOld = indexOne;
+						//endOfDifferencesNew = indexTwo;
+						break;
+					}
+					indexOld--;
+					indexNew--;
+				}
+				endOfDifferencesOld = indexOld;
+				endOfDifferencesNew = indexNew;
+			}
+		}
+		//
+		// result != null means the impossible case above occurred
+		if (result == null) {
+			// Now form the two vectors of different regions
+			ITextRegionList holdOldRegions = new TextRegionListImpl();
+			ITextRegionList holdNewRegions = new TextRegionListImpl();
+			if (startOfDifferences > -1 && endOfDifferencesOld > -1) {
+				for (int i = startOfDifferences; i <= endOfDifferencesOld; i++) {
+					holdOldRegions.add(oldRegionsArray[i]);
+				}
+			}
+			if (startOfDifferences > -1 && endOfDifferencesNew > -1) {
+				for (int i = startOfDifferences; i <= endOfDifferencesNew; i++) {
+					holdNewRegions.add(newRegionsArray[i]);
+				}
+			}
+			if (holdOldRegions.size() == 0 && holdNewRegions.size() == 0) {
+				// then this means the regions were identical, which means
+				// someone
+				// pasted exactly the same thing they had selected, or !!!
+				// someone deleted the end bracket of the tag. !!!?
+				result = new NoChangeEvent(fStructuredDocument, fRequester, fChanges, fStart, fLengthToReplace);
+			} else {
+				//If both holdOldRegions and holdNewRegions are of length 1,
+				// then its
+				// a "region changed" event, else a "regions replaced" event.
+				// so we want the new instance of region to become part of the
+				// old instance of old node
+				if ((holdOldRegions.size() == 1) && (holdNewRegions.size() == 1) && _regionsSameKind((holdNewRegions.get(0)), (holdOldRegions.get(0)))) {
+					ITextRegion newOldRegion = swapNewForOldRegion(oldNode, holdOldRegions.get(0), newNode, holdNewRegions.get(0));
+					// -- need to update any down stream regions, within this
+					// 'oldNode'
+					updateDownStreamRegions(oldNode, newOldRegion);
+					result = new RegionChangedEvent(fStructuredDocument, fRequester, oldNode, newOldRegion, fChanges, fStart, fLengthToReplace);
+				} else {
+					replaceRegions(oldNode, holdOldRegions, newNode, holdNewRegions);
+					// -- need to update any down stream regions, within this
+					// 'oldNode'
+					// don't need with the way replaceRegions is implemented.
+					// It handles.
+					//if(holdNewRegions.size() > 0)
+					//updateDownStreamRegions(oldNode, (ITextRegion)
+					// holdNewRegions.lastElement());
+					result = new RegionsReplacedEvent(fStructuredDocument, fRequester, oldNode, holdOldRegions, holdNewRegions, fChanges, fStart, fLengthToReplace);
+				}
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * An entry point for reparsing. It calculates the dirty start and dirty
+	 * end flatnodes based on the start point and length of the changes.
+	 *  
+	 */
+	public StructuredDocumentEvent reparse() {
+		StructuredDocumentEvent result = null;
+		// if we do not have a cachedNode, then the document
+		// must be empty, so simply use 'null' as the dirtyStart and dirtyEnd
+		// otherwise, find them.
+		if (fStructuredDocument.getCachedDocumentRegion() != null) {
+			findDirtyStart(fStart);
+			int end = fStart + fLengthToReplace;
+			findDirtyEnd(end);
+		}
+		if (fStructuredDocument.getCachedDocumentRegion() != null) {
+			result = checkHeuristics();
+		}
+		if (result == null) {
+			result = reparse(dirtyStart, dirtyEnd);
+		}
+		endReParse();
+		return result;
+	}
+
+	/**
+	 * An entry point for reparsing. It calculates the dirty start and dirty
+	 * end flatnodes based on suggested positions to begin and end. This is
+	 * needed for cases where parsing must go beyond the immediate node and
+	 * its direct neighbors.
+	 *  
+	 */
+	protected StructuredDocumentEvent reparse(int reScanStartHint, int reScanEndHint) {
+		StructuredDocumentEvent result = null;
+		// if we do not have a cachedNode, then the document
+		// must be empty, so simply use 'null' as the dirtyStart and dirtyEnd
+		if (fStructuredDocument.getCachedDocumentRegion() != null) {
+			findDirtyStart(reScanStartHint);
+			findDirtyEnd(reScanEndHint);
+		}
+		result = reparse(dirtyStart, dirtyEnd);
+		isParsing = false;
+		// debug
+		//verifyStructured(result);
+		return result;
+	}
+
+	/**
+	 * The core reparsing method ... after the dirty start and dirty end have
+	 * been calculated elsewhere.
+	 */
+	protected StructuredDocumentEvent reparse(IStructuredDocumentRegion dirtyStart, IStructuredDocumentRegion dirtyEnd) {
+		StructuredDocumentEvent result = null;
+		int rescanStart = -1;
+		int rescanEnd = -1;
+		boolean firstTime = false;
+		//
+		// "save" the oldNodes (that may be replaced) in a list
+		CoreNodeList oldNodes = formOldNodes(dirtyStart, dirtyEnd);
+		if (dirtyStart == null || dirtyEnd == null) {
+			// dirtyStart or dirty end are null, then that means we didn't
+			// have
+			// a
+			// cached node, which means we have an empty document, so we
+			// just need to rescan the changes
+			rescanStart = 0;
+			rescanEnd = fChanges.length();
+			firstTime = true;
+		} else {
+			// set the start of the text to rescan
+			rescanStart = dirtyStart.getStart();
+			//
+			// set the end of the text to rescan
+			// notice we use the same rationale as for the rescanStart,
+			// with the added caveat that length has to be added to it,
+			// to compensate for the new text which has been added or deleted.
+			// If changes has zero length, then "length" will be negative,
+			// since
+			// we are deleting text. Otherwise, use the difference between
+			// what's selected to be replaced and the length of the new text.
+			rescanEnd = dirtyEnd.getEnd() + fLengthDifference;
+		}
+		// now that we have the old stuff "saved" away, update the document
+		// with the changes.
+		// FUTURE_TO_DO -- don't fire "document changed" event till later
+		fStructuredDocument.updateDocumentData(fStart, fLengthToReplace, fChanges);
+		// ------------------ now the real work
+		result = core_reparse(rescanStart, rescanEnd, oldNodes, firstTime);
+		//
+		// event is returned to the caller, incase there is
+		// some opitmization they can do
+		return result;
+	}
+
+	protected void replaceRegions(IStructuredDocumentRegion oldNode, ITextRegionList oldRegions, IStructuredDocumentRegion newNode, ITextRegionList newRegions) {
+		int insertPos = -1;
+		ITextRegionList regions = oldNode.getRegions();
+		// make a fake flatnode to be new parent of oldRegions, so their text
+		// will be right.
+		//IStructuredDocumentRegion holdOldStructuredDocumentRegion = new
+		// BasicStructuredDocumentRegion(oldNode);
+		//
+		// need to reset the parent of the new to-be-inserted regions to be
+		// the
+		// same oldNode that is the one having its regions changed
+		// DW, 4/16/2003, removed since ITextRegion no longer has parent.
+		// 		ITextRegionContainer oldParent = oldNode;
+		//		for (int i = 0; i < newRegions.size(); i++) {
+		//			AbstractRegion region = (AbstractRegion) newRegions.elementAt(i);
+		//			region.setParent(oldParent);
+		//		}
+		// if there are no old regions, insert the new regions according to
+		// offset
+		if (oldRegions.size() == 0) {
+			ITextRegion firstNewRegion = newRegions.get(0);
+			int firstOffset = newNode.getStartOffset(firstNewRegion);
+			// if at beginning, insert there
+			if (firstOffset == 0) {
+				insertPos = 0;
+			} else {
+				//
+				ITextRegion regionAtOffset = oldNode.getRegionAtCharacterOffset(firstOffset);
+				if (regionAtOffset == null)
+					insertPos = regions.size();
+				else
+					insertPos = regions.indexOf(regionAtOffset);
+			}
+		} else {
+			// else, delete old ones before inserting new ones in their place
+			ITextRegion firstOldRegion = oldRegions.get(0);
+			insertPos = regions.indexOf(firstOldRegion);
+			regions.removeAll(oldRegions);
+		}
+		regions.addAll(insertPos, newRegions);
+		// now regions vector of each node should be of equal length,
+		// so go through each, and make sure the old regions
+		// offsets matches the new regions offsets
+		// (we'll just assign them all, but could be slightly more effiecient)
+		ITextRegionList allNewRegions = newNode.getRegions();
+		for (int i = 0; i < regions.size(); i++) {
+			ITextRegion nextOldishRegion = regions.get(i);
+			ITextRegion nextNewRegion = allNewRegions.get(i);
+			nextOldishRegion.equatePositions(nextNewRegion);
+			checkAndAssignParent(oldNode, nextOldishRegion);
+		}
+		oldNode.setLength(newNode.getLength());
+		oldNode.setEnded(newNode.isEnded());
+		oldNode.setParentDocument(newNode.getParentDocument());
+		// removed concept of part of these regions, so no longer need to do.
+		//		for (int i = 0; i < oldRegions.size(); i++) {
+		//			ITextRegion region = (ITextRegion) oldRegions.elementAt(i);
+		//			region.setParent(holdOldStructuredDocumentRegion);
+		//		}
+	}
+
+	private void reSetCachedNode(CoreNodeList oldNodes, CoreNodeList newNodes) {
+		// use the last newNode as the new cachedNode postion, unless its null
+		// (e.g. when nodes are deleted) in which case, assign
+		// it to a "safe" node so we don't lose reference to the
+		// structuredDocument!
+		if (newNodes.getLength() > 0) {
+			// use last new node as the cache
+			fStructuredDocument.setCachedDocumentRegion(newNodes.item(newNodes.getLength() - 1));
+		} else {
+			// if cachedNode is an old node, then we're in trouble:
+			// we can't leave it as the cached node! and its already
+			// been disconnected from the model, so we can't do getNext
+			// or getPrevious, so we'll get one that is right before
+			// (or right after) the offset of the old nodes that are being
+			// deleted.
+			// 
+			// if newNodesHead and cachedNode are both null, then
+			// it means we were asked to insert an empty string into
+			// an empty document. So we have nothing to do here
+			// (that is, we have no node to cache)
+			// similarly if there are no new nodes and no old nodes then
+			// nothing to do (but that should never happen ... we shouldn't
+			// get there if there is no event to generate).
+			if ((fStructuredDocument.getCachedDocumentRegion() != null) && (oldNodes.getLength() > 0)) {
+				// note: we can't simple use nodeAtCharacterOffset, since it
+				// depends on cachedNode.
+				if (oldNodes.includes(fStructuredDocument.getCachedDocumentRegion()))
+					fStructuredDocument.setCachedDocumentRegion(fStructuredDocument.getFirstStructuredDocumentRegion());
+			}
+			if ((fStructuredDocument.getCachedDocumentRegion() == null) && (Debug.displayWarnings)) {
+				// this will happen now legitamately when all text is deleted
+				// from a document
+				System.out.println("Warning: StructuredDocumentReParser::reSetCachedNode: could not find a node to cache! (its ok if all text deleted)"); //$NON-NLS-1$
+			}
+		}
+	}
+
+	public void setStructuredDocument(IStructuredDocument newStructuredDocument) {
+		// NOTE: this method (and class) depend on being able to
+		// do the following cast (i.e. references some fields directly)
+		fStructuredDocument = (BasicStructuredDocument) newStructuredDocument;
+		fFindReplaceDocumentAdapter = null;
+	}
+
+	private IStructuredDocumentRegion splice(CoreNodeList oldNodes, CoreNodeList newNodes) {
+		//
+		IStructuredDocumentRegion firstOld = null;
+		IStructuredDocumentRegion firstNew = null;
+		IStructuredDocumentRegion lastOld = null;
+		IStructuredDocumentRegion lastNew = null;
+		//
+		IStructuredDocumentRegion oldPrevious = null;
+		IStructuredDocumentRegion oldNext = null;
+		IStructuredDocumentRegion newPrevious = null;
+		IStructuredDocumentRegion newNext = null;
+		//
+		// if called with both arguments empty lists, we can disregard.
+		// this happens, for example, when some text is replaced with the
+		// identical text.
+		if ((oldNodes.getLength() == 0) && (newNodes.getLength() == 0)) {
+			return null;
+		}
+		// get pointers
+		if (newNodes.getLength() > 0) {
+			firstNew = newNodes.item(0);
+			lastNew = newNodes.item(newNodes.getLength() - 1);
+		}
+		//
+		if (oldNodes.getLength() > 0) {
+			firstOld = oldNodes.item(0);
+			lastOld = oldNodes.item(oldNodes.getLength() - 1);
+			if (firstOld != null)
+				oldPrevious = firstOld.getPrevious();
+			if (lastOld != null)
+				oldNext = lastOld.getNext();
+		}
+		// handle switch
+		if (newNodes.getLength() > 0) {
+			// switch surrounding StructuredDocumentRegions' references to
+			// lists
+			if (oldPrevious != null)
+				oldPrevious.setNext(firstNew);
+			if (newPrevious != null)
+				newPrevious.setNext(firstOld);
+			if (oldNext != null)
+				oldNext.setPrevious(lastNew);
+			if (newNext != null)
+				newNext.setPrevious(lastOld);
+			// switch list pointers to surrounding StructuredDocumentRegions
+			if (firstOld != null)
+				firstOld.setPrevious(newPrevious);
+			if (lastOld != null)
+				lastOld.setNext(newNext);
+			if (firstNew != null)
+				firstNew.setPrevious(oldPrevious);
+			if (lastNew != null)
+				lastNew.setNext(oldNext);
+		} else {
+			// short circuit when there are no new nodes
+			if (oldPrevious != null)
+				oldPrevious.setNext(oldNext);
+			if (oldNext != null)
+				oldNext.setPrevious(oldPrevious);
+		}
+		//
+		// SIDE EFFECTs
+		// if we have oldNodes, and if oldNext or oldPrevious is null,
+		// that means we are replacing
+		// the lastNode or firstNode the structuredDocuments's chain of nodes,
+		// so we need to update the structuredDocuments last or first Node
+		// as the last or first of the new nodes.
+		// (and sometimes even these will be null! such as when deleting all
+		// text in a document).
+		if ((oldNext == null) && (oldNodes.getLength() > 0)) {
+			if (newNodes.getLength() > 0) {
+				fStructuredDocument.setLastDocumentRegion(lastNew);
+			} else {
+				// in this case, the last node is being deleted, but not
+				// replaced
+				// with anything. In this case, we can just back up one
+				// from the first old node
+				fStructuredDocument.setLastDocumentRegion(firstOld.getPrevious());
+			}
+		}
+		if ((oldPrevious == null) && (oldNodes.getLength() > 0)) {
+			if (newNodes.getLength() > 0) {
+				fStructuredDocument.setFirstDocumentRegion(firstNew);
+			} else {
+				// in this case the first node is being deleted, but not
+				// replaced
+				// with anything. So, we just go one forward past the last old
+				// node.
+				fStructuredDocument.setFirstDocumentRegion(lastOld.getNext());
+			}
+		}
+		// as a tiny optimization, we return the first of the downstream
+		// nodes,
+		// if any
+		return oldNext;
+	}
+
+	/**
+	 * The purpose of this method is to "reuse" the old container region, when
+	 * found to be same (so same instance doesn't change). The goal is to
+	 * "transform" the old region, so its equivelent to the newly parsed one.
+	 *  
+	 */
+	private ITextRegion swapNewForOldRegion(IStructuredDocumentRegion oldNode, ITextRegion oldRegion, IStructuredDocumentRegion newNode, ITextRegion newRegion) {
+		// makes the old region instance the correct size.
+		oldRegion.equatePositions(newRegion);
+		// adjusts old node instance appropriately
+		oldNode.setLength(newNode.getLength());
+		oldNode.setEnded(newNode.isEnded());
+		// we do have to set the parent document, since the oldNode's
+		// were set to a temporary one, then newNode's have the
+		// right one.
+		oldNode.setParentDocument(newNode.getParentDocument());
+		// if we're transforming a container region, we need to be sure to
+		// transfer the new embedded regions, to the old parent
+		// Note: if oldRegion hasEmbeddedRegions, then we know the
+		// newRegion does too, since we got here because they were the
+		// same type.
+		if (isCollectionRegion(oldRegion)) { // ||
+			// hasContainerRegions(oldRegion))
+			// {
+			transferEmbeddedRegions(oldNode, (ITextRegionContainer) oldRegion, (ITextRegionContainer) newRegion);
+		}
+		return oldRegion;
+	}
+
+	private IStructuredDocumentRegion switchNodeLists(CoreNodeList oldNodes, CoreNodeList newNodes) {
+		IStructuredDocumentRegion result = splice(oldNodes, newNodes);
+		// ensure that the old nodes hold no references to the existing model
+		if (oldNodes.getLength() > 0) {
+			IStructuredDocumentRegion firstItem = oldNodes.item(0);
+			firstItem.setPrevious(null);
+			IStructuredDocumentRegion lastItem = oldNodes.item(oldNodes.getLength() - 1);
+			lastItem.setNext(null);
+		}
+		return result;
+	}
+
+	/**
+	 * The purpose of this method is to "reuse" the old container region, when
+	 * found to be same (so same instance doesn't change). The goal is to
+	 * "transform" the old region, so its equivelent to the newly parsed one.
+	 *  
+	 */
+	private void transferEmbeddedRegions(IStructuredDocumentRegion oldNode, ITextRegionContainer oldRegion, ITextRegionContainer newRegion) {
+		// the oldRegion should already have the right parent, since
+		// we got here because all's equivelent except the region
+		// postions have changed.
+		//oldRegion.setParent(newRegion.getParent());
+		// but we should check if there's "nested" embedded regions, and if
+		// so, we can just move them over. setting their parent as this old
+		// region.
+		ITextRegionList newRegionsToTransfer = newRegion.getRegions();
+		oldRegion.setRegions(newRegionsToTransfer);
+		Iterator newRegionsInOldOne = newRegionsToTransfer.iterator();
+		while (newRegionsInOldOne.hasNext()) {
+			ITextRegion newOne = (ITextRegion) newRegionsInOldOne.next();
+			if (isCollectionRegion(newOne)) { // ||
+				// hasContainerRegions(newOne)) {
+				//((ITextRegionContainer) newOne).setParent(oldRegion);
+				oldRegion.setRegions(newRegion.getRegions());
+			}
+		}
+	}
+
+	private void updateDownStreamRegions(IStructuredDocumentRegion flatNode, ITextRegion lastKnownRegion) {
+		// so all regions after the last known region (last known to be ok)
+		// have to have their start and end values adjusted.
+		ITextRegionList regions = flatNode.getRegions();
+		int listLength = regions.size();
+		int startIndex = 0;
+		// first, loop through to find where to start
+		for (int i = 0; i < listLength; i++) {
+			ITextRegion region = regions.get(i);
+			if (region == lastKnownRegion) {
+				startIndex = i;
+				break;
+			}
+		}
+		// now, beginning one past the last known one, loop
+		// through to end of list, adjusting the start and end postions.
+		startIndex++;
+		for (int j = startIndex; j < listLength; j++) {
+			ITextRegion region = regions.get(j);
+			region.adjustStart(fLengthDifference);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentRegionEnumeration.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentRegionEnumeration.java
new file mode 100644
index 0000000..1191198
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentRegionEnumeration.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.util.Debug;
+
+
+public class StructuredDocumentRegionEnumeration implements Enumeration {
+
+	private int count;
+	private IStructuredDocumentRegion head;
+	private IStructuredDocumentRegion oldHead;
+
+	/**
+	 * StructuredDocumentRegionEnumeration constructor comment.
+	 */
+	public StructuredDocumentRegionEnumeration(IStructuredDocumentRegion newHead) {
+		super();
+		IStructuredDocumentRegion countNode = head = newHead;
+		while (countNode != null) {
+			count++;
+			countNode = countNode.getNext();
+		}
+		if (Debug.DEBUG > 5) {
+			System.out.println("N Nodes in StructuredDocumentRegionEnumeration Contructor: " + count); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * StructuredDocumentRegionEnumeration constructor comment.
+	 */
+	public StructuredDocumentRegionEnumeration(IStructuredDocumentRegion start, IStructuredDocumentRegion end) {
+		super();
+		IStructuredDocumentRegion countNode = head = start;
+		if ((start == null) || (end == null)) {
+			// error condition
+			count = 0;
+			return;
+		}
+		//If both nodes are non-null, we assume there is always at least one
+		// item
+		count = 1;
+		while (countNode != end) {
+			count++;
+			countNode = countNode.getNext();
+		}
+		if (org.eclipse.wst.sse.core.internal.util.Debug.DEBUG > 5) {
+			System.out.println("N Nodes in StructuredDocumentRegionEnumeration Contructor: " + count); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * hasMoreElements method comment.
+	 */
+	public synchronized boolean hasMoreElements() {
+		return count > 0;
+	}
+
+	/**
+	 * nextElement method comment.
+	 */
+	public synchronized Object nextElement() {
+		if (count > 0) {
+			count--;
+			oldHead = head;
+			head = head.getNext();
+			return oldHead;
+		}
+		throw new NoSuchElementException("StructuredDocumentRegionEnumeration"); //$NON-NLS-1$
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentRegionIterator.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentRegionIterator.java
new file mode 100644
index 0000000..c121b31
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentRegionIterator.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+
+
+import java.util.Vector;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+
+
+public class StructuredDocumentRegionIterator {
+
+	public final static IStructuredDocumentRegion adjustStart(IStructuredDocumentRegion headNode, int adjustment) {
+		IStructuredDocumentRegion aNode = headNode;
+		while (aNode != null) {
+			aNode.adjustStart(adjustment);
+			aNode = aNode.getNext();
+		}
+		return headNode;
+	}
+
+	public final static int countRegions(IStructuredDocumentRegionList flatNodes) {
+		int result = 0;
+		if (flatNodes != null) {
+			int length = flatNodes.getLength();
+			for (int i = 0; i < length; i++) {
+				IStructuredDocumentRegion node = flatNodes.item(i);
+				// don't know why, but we're getting null pointer exceptions
+				// in this method
+				if (node != null) {
+					result = result + node.getNumberOfRegions();
+				}
+			}
+		}
+		return result;
+	}
+
+	public final static String getText(CoreNodeList flatNodes) {
+		String result = null;
+		if (flatNodes == null) {
+			result = ""; //$NON-NLS-1$
+		} else {
+			StringBuffer buff = new StringBuffer();
+			//IStructuredDocumentRegion aNode = null;
+			int length = flatNodes.getLength();
+			for (int i = 0; i < length; i++) {
+				buff.append(flatNodes.item(i).getText());
+			}
+			result = buff.toString();
+		}
+		return result;
+	}
+
+	public final static CoreNodeList setParentDocument(CoreNodeList nodelist, IStructuredDocument textStore) {
+		Assert.isNotNull(nodelist, "nodelist was null in CoreNodeList::setTextStore(CoreNodeList, StructuredTextStore)"); //$NON-NLS-1$
+		int len = nodelist.getLength();
+		for (int i = 0; i < len; i++) {
+			IStructuredDocumentRegion node = nodelist.item(i);
+			//Assert.isNotNull(node, "who's putting null in the node list? in
+			// CoreNodeList::setTextStore(CoreNodeList,
+			// StructuredTextStore)"); //$NON-NLS-1$
+			node.setParentDocument(textStore);
+		}
+		return nodelist;
+	}
+
+	//	public final static IStructuredDocumentRegion
+	// setStructuredDocument(IStructuredDocumentRegion headNode,
+	// BasicStructuredDocument structuredDocument) {
+	//		IStructuredDocumentRegion aNode = headNode;
+	//		while (aNode != null) {
+	//			aNode.setParentDocument(structuredDocument);
+	//			aNode = (IStructuredDocumentRegion) aNode.getNext();
+	//		}
+	//		return headNode;
+	//	}
+	public final static IStructuredDocumentRegion setParentDocument(IStructuredDocumentRegion headNode, IStructuredDocument document) {
+		IStructuredDocumentRegion aNode = headNode;
+		while (aNode != null) {
+			aNode.setParentDocument(document);
+			aNode = aNode.getNext();
+		}
+		return headNode;
+	}
+
+	public final static Vector toVector(IStructuredDocumentRegion headNode) {
+		IStructuredDocumentRegion aNode = headNode;
+		Vector v = new Vector();
+		while (aNode != null) {
+			v.addElement(aNode);
+			aNode = aNode.getNext();
+		}
+		return v;
+	}
+
+	/**
+	 *  
+	 */
+	private StructuredDocumentRegionIterator() {
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentSequentialRewriteTextStore.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentSequentialRewriteTextStore.java
new file mode 100644
index 0000000..5c31aa8
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentSequentialRewriteTextStore.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+import org.eclipse.jface.text.ITextStore;
+import org.eclipse.jface.text.SequentialRewriteTextStore;
+
+public class StructuredDocumentSequentialRewriteTextStore extends SequentialRewriteTextStore implements CharSequence, IRegionComparible {
+
+	/**
+	 * @param source
+	 */
+	public StructuredDocumentSequentialRewriteTextStore(ITextStore source) {
+		super(source);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.CharSequence#charAt(int)
+	 */
+	public char charAt(int index) {
+		return get(index);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.CharSequence#length()
+	 */
+	public int length() {
+		return getLength();
+	}
+
+	/**
+	 * @param c
+	 * @param d
+	 * @return
+	 */
+	private boolean matchesIgnoreCase(char c1, char c2) {
+		// we check both case conversions to handle those few cases,
+		// in languages such as Turkish, which have some characters
+		// which sort of have 3 cases.
+		boolean result = false;
+		if (Character.toUpperCase(c1) == Character.toUpperCase(c2))
+			result = true;
+		else if (Character.toLowerCase(c1) == Character.toLowerCase(c2))
+			result = true;
+		return result;
+	}
+
+	public boolean regionMatches(int offset, int length, String stringToCompare) {
+		boolean result = false;
+		int compareLength = stringToCompare.length();
+		if (compareLength == length) {
+			int endOffset = offset + length;
+			if (endOffset <= length()) {
+				result = regionMatches(offset, stringToCompare);
+			}
+		}
+
+		return result;
+	}
+
+	/**
+	 * This method assumes all lengths have been checked and fall withint
+	 * exceptable limits
+	 * 
+	 * @param offset
+	 * @param stringToCompare
+	 * @return
+	 */
+	private boolean regionMatches(int offset, String stringToCompare) {
+		boolean result = true;
+		int stringOffset = 0;
+		int len = stringToCompare.length();
+		for (int i = offset; i < len; i++) {
+			if (charAt(i) != stringToCompare.charAt(stringOffset++)) {
+				result = false;
+				break;
+			}
+		}
+		return result;
+	}
+
+	public boolean regionMatchesIgnoreCase(int offset, int length, String stringToCompare) {
+		boolean result = false;
+		int compareLength = stringToCompare.length();
+		if (compareLength == length) {
+			int endOffset = offset + length;
+			if (endOffset <= length()) {
+				result = regionMatchesIgnoreCase(offset, stringToCompare);
+			}
+		}
+
+		return result;
+	}
+
+	private boolean regionMatchesIgnoreCase(int offset, String stringToCompare) {
+		boolean result = true;
+		int stringOffset = 0;
+		int len = stringToCompare.length();
+		for (int i = offset; i < len; i++) {
+			if (!matchesIgnoreCase(charAt(i), stringToCompare.charAt(stringOffset++))) {
+				result = false;
+				break;
+			}
+		}
+		return result;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.CharSequence#subSequence(int, int)
+	 */
+	public CharSequence subSequence(int start, int end) {
+
+		return get(start, end - start);
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentTextStore.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentTextStore.java
new file mode 100644
index 0000000..e825e72
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/StructuredDocumentTextStore.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Viacheslav Kabanovich/Exadel 97817 Wrong algoritm in class StructuredDocumentTextStore
+ *     			https://bugs.eclipse.org/bugs/show_bug.cgi?id=97817
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+import org.eclipse.jface.text.GapTextStore;
+import org.eclipse.jface.text.ITextStore;
+
+public class StructuredDocumentTextStore implements ITextStore, CharSequence, IRegionComparible {
+
+	private GapTextStore fInternalStore;
+
+	/**
+	 *  
+	 */
+	public StructuredDocumentTextStore() {
+		this(50, 300);
+	}
+
+	/**
+	 * @param lowWatermark
+	 * @param highWatermark
+	 */
+	public StructuredDocumentTextStore(int lowWatermark, int highWatermark) {
+		super();
+		fInternalStore = new GapTextStore(lowWatermark, highWatermark);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.CharSequence#charAt(int)
+	 */
+	public char charAt(int index) {
+		return fInternalStore.get(index);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.ITextStore#get(int)
+	 */
+	public char get(int offset) {
+
+		return fInternalStore.get(offset);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.ITextStore#get(int, int)
+	 */
+	public String get(int offset, int length) {
+
+		return fInternalStore.get(offset, length);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.ITextStore#getLength()
+	 */
+	public int getLength() {
+
+		return fInternalStore.getLength();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.CharSequence#length()
+	 */
+	public int length() {
+
+		return fInternalStore.getLength();
+	}
+
+	private boolean matchesIgnoreCase(char c1, char c2) {
+		// we check both case conversions to handle those few cases,
+		// in languages such as Turkish, which have some characters
+		// which sort of have 3 cases.
+		boolean result = false;
+		if (Character.toUpperCase(c1) == Character.toUpperCase(c2))
+			result = true;
+		else if (Character.toLowerCase(c1) == Character.toLowerCase(c2))
+			result = true;
+		return result;
+	}
+
+	public boolean regionMatches(int offset, int length, String stringToCompare) {
+		boolean result = false;
+		int compareLength = stringToCompare.length();
+		if (compareLength == length) {
+			int endOffset = offset + length;
+			if (endOffset <= length()) {
+				result = regionMatches(offset, stringToCompare);
+			}
+		}
+
+		return result;
+	}
+
+	/**
+	 * This method assumes all lengths have been checked and fall withint
+	 * exceptable limits
+	 * 
+	 * @param offset
+	 * @param stringToCompare
+	 * @return
+	 */
+	private boolean regionMatches(int offset, String stringToCompare) {
+		boolean result = true;
+		int stringOffset = 0;
+		int end = offset + stringToCompare.length();
+		for (int i = offset; i < end; i++) {
+			if (charAt(i) != stringToCompare.charAt(stringOffset++)) {
+				result = false;
+				break;
+			}
+		}
+		return result;
+	}
+
+	public boolean regionMatchesIgnoreCase(int offset, int length, String stringToCompare) {
+		boolean result = false;
+		int compareLength = stringToCompare.length();
+		if (compareLength == length) {
+			int endOffset = offset + length;
+			if (endOffset <= length()) {
+				result = regionMatchesIgnoreCase(offset, stringToCompare);
+			}
+		}
+
+		return result;
+	}
+
+	private boolean regionMatchesIgnoreCase(int offset, String stringToCompare) {
+		boolean result = true;
+		int stringOffset = 0;
+		int end = offset + stringToCompare.length();
+		for (int i = offset; i < end; i++) {
+			if (!matchesIgnoreCase(charAt(i), stringToCompare.charAt(stringOffset++))) {
+				result = false;
+				break;
+			}
+		}
+		return result;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.ITextStore#replace(int, int,
+	 *      java.lang.String)
+	 */
+	public void replace(int offset, int length, String text) {
+		fInternalStore.replace(offset, length, text);
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.text.ITextStore#set(java.lang.String)
+	 */
+	public void set(String text) {
+		fInternalStore.set(text);
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.CharSequence#subSequence(int, int)
+	 */
+	public CharSequence subSequence(int start, int end) {
+		// convert 'end' to 'length'
+		return fInternalStore.get(start, end - start);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/SubSetTextStore.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/SubSetTextStore.java
new file mode 100644
index 0000000..caca8b9
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/SubSetTextStore.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+/**
+ * This is a convience or utility class that allows you to make a copy of a
+ * part of a larger text store, but have the copy behave as if it was the
+ * larger text store.
+ * 
+ * In other words, it provides a subset of a larger document, that "looks like"
+ * the orginal document. That is, "looks like" in terms of offsets and lengths.
+ * Valid access can only be made to data between the orignal offsets, even
+ * though those offsets are in the same units at the original, and even though
+ * the length appears to be long.
+ * 
+ * For example, if a subsettext store is created for the def part of abcdefgh,
+ * then get(3,5) is valid, getLength is 8. Any other access, such as
+ * getChar(2), would be invalid.
+ */
+import org.eclipse.jface.text.ITextStore;
+
+/**
+ * Similar to basics of IDocument, but the offsets are mapped from coordinates
+ * of underlying storage to a "virtual" document.
+ */
+public class SubSetTextStore implements ITextStore {
+	private int pseudoBeginOffset; // maps to "zero" postion of new text
+	//private int pseudoEndOffset;
+	private int pseudoLength; // length of old/original document
+	private StringBuffer stringBuffer = new StringBuffer();
+
+	/**
+	 * SubSetTextStore constructor comment.
+	 * 
+	 * @param initialContent
+	 *            java.lang.String
+	 */
+	public SubSetTextStore(String initialContent, int beginOffset, int endOffset, int originalDocumentLength) {
+		super();
+		pseudoBeginOffset = beginOffset;
+		//pseudoEndOffset = endOffset;
+		// used to be originalDocument.getLength ... not sure if used, or
+		// which
+		// is right
+		pseudoLength = originalDocumentLength;
+		stringBuffer = new StringBuffer(initialContent);
+		//set(initialContent);
+	}
+
+	// this is our "private" get, which methods in this class should
+	// use to get using "real" coordinates of underlying representation.
+	private String _get(int begin, int length) {
+		char[] chars = new char[length];
+		int srcEnd = begin + length;
+		stringBuffer.getChars(begin, srcEnd, chars, 0);
+		return new String(chars);
+	}
+
+	public char get(int offset) {
+		return stringBuffer.charAt(offset - pseudoBeginOffset);
+	}
+
+	/**
+	 * @return java.lang.String
+	 * @param begin
+	 *            int
+	 * @param end
+	 *            int
+	 */
+	public String get(int begin, int length) {
+		// remap the begin and end to "appear" to be in the
+		// same coordinates of the original parentDocument
+		return _get(begin - pseudoBeginOffset, length);
+	}
+
+	/**
+	 * @return java.lang.String
+	 * @param begin
+	 *            int
+	 * @param end
+	 *            int
+	 */
+	public char getChar(int pos) {
+		// remap the begin and end to "appear" to be in the
+		// same coordinates of the original parentDocument
+		return get(pos - pseudoBeginOffset);
+	}
+
+	/**
+	 * We redefine getLength so its not the true length of this sub-set
+	 * document, but the length of the original. This is needed, as a simple
+	 * example, if you want to see if the pseudo end is equal the last
+	 * position of the original document.
+	 */
+	public int getLength() {
+		return pseudoLength;
+	}
+
+	/**
+	 * Returns the length as if considered a true, standalone document
+	 */
+	public int getTrueLength() {
+		return stringBuffer.length();
+	}
+
+	public void replace(int begin, int length, String changes) {
+		// remap the begin and end to "appear" to be in the
+		// same coordinates of the original parentDocument
+		int end = begin + length;
+		stringBuffer.replace(begin - pseudoBeginOffset, end, changes);
+	}
+
+	public void set(String text) {
+		stringBuffer.setLength(0);
+		stringBuffer.append(text);
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/TextRegionListImpl.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/TextRegionListImpl.java
new file mode 100644
index 0000000..9f62b78
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/TextRegionListImpl.java
@@ -0,0 +1,236 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (Intalio) - bug 300434 - Make inner classes static where possible
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+
+
+public class TextRegionListImpl implements ITextRegionList {
+
+	static private class NullIterator implements Iterator {
+		public NullIterator() {
+		}
+
+		public boolean hasNext() {
+			return false;
+		}
+
+		public Object next() {
+			throw new NoSuchElementException();
+		}
+
+		public void remove() {
+			throw new UnsupportedOperationException("can not remove regions via iterator"); //$NON-NLS-1$
+
+		}
+
+	}
+
+	private static class RegionIterator implements Iterator {
+		private ITextRegion[] fIteratorRegions;
+		private int index = -1;
+		private int maxindex = -1;
+
+		public RegionIterator(ITextRegion[] regions) {
+			fIteratorRegions = regions;
+			maxindex = fIteratorRegions.length - 1;
+		}
+
+		public boolean hasNext() {
+			return index < maxindex;
+		}
+
+		public Object next() {
+			if (!(index < maxindex))
+				throw new NoSuchElementException();
+			return fIteratorRegions[++index];
+		}
+
+		public void remove() {
+			if (index < 0) {
+				// next() has never been called
+				throw new IllegalStateException("can not remove regions without prior invocation of next()"); //$NON-NLS-1$
+			}
+			throw new UnsupportedOperationException("can not remove regions via iterator"); //$NON-NLS-1$
+		}
+
+	}
+
+	private final static int growthConstant = 2;
+
+	private ITextRegion[] fRegions;
+	private int fRegionsCount = 0;
+
+	public TextRegionListImpl() {
+		super();
+	}
+
+	public TextRegionListImpl(ITextRegionList regionList) {
+		this();
+		fRegions = (ITextRegion[]) regionList.toArray().clone();
+		fRegionsCount = fRegions.length;
+	}
+
+	public boolean add(ITextRegion region) {
+		if (region == null)
+			return false;
+		ensureCapacity(fRegionsCount + 1);
+		fRegions[fRegionsCount++] = region;
+		return true;
+	}
+
+	public boolean addAll(int insertPos, ITextRegionList newRegionList) {
+		// beginning of list is 0 to insertPos-1
+		// remainder of list is insertPos to fRegionsCount
+		// resulting total will be be fRegionsCount + newRegions.size()
+		if (insertPos < 0 || insertPos > fRegionsCount) {
+			throw new ArrayIndexOutOfBoundsException(insertPos);
+		}
+
+		int newRegionListSize = newRegionList.size();
+
+		ensureCapacity(fRegionsCount + newRegionListSize);
+
+		int numMoved = fRegionsCount - insertPos;
+		if (numMoved > 0)
+			System.arraycopy(fRegions, insertPos, fRegions, insertPos + newRegionListSize, numMoved);
+
+		if (newRegionList instanceof TextRegionListImpl && ((TextRegionListImpl) newRegionList).fRegions != null) {
+			System.arraycopy(((TextRegionListImpl) newRegionList).fRegions, 0, fRegions, insertPos, newRegionListSize);
+		}
+		else {
+			for (int i = 0; i < newRegionListSize; i++) {
+				fRegions[insertPos++] = newRegionList.get(i);
+			}
+		}
+		fRegionsCount += newRegionListSize;
+		return newRegionListSize != 0;
+	}
+
+	public void clear() {
+		// note: size of array is not reduced!
+		fRegionsCount = 0;
+	}
+
+	private void ensureCapacity(int needed) {
+		if (fRegions == null) {
+			// first time
+			fRegions = new ITextRegion[needed];
+			return;
+		}
+		int oldLength = fRegions.length;
+		if (oldLength < needed) {
+			ITextRegion[] oldAdapters = fRegions;
+			ITextRegion[] newAdapters = new ITextRegion[needed + growthConstant];
+			System.arraycopy(oldAdapters, 0, newAdapters, 0, fRegionsCount);
+			fRegions = newAdapters;
+		}
+	}
+
+	public ITextRegion get(int index) {
+		// fRegionCount may not equal fRegions.length
+		if (index < 0 || index >= fRegionsCount) {
+			throw new ArrayIndexOutOfBoundsException(index);
+		}
+		return fRegions[index];
+	}
+
+	public int indexOf(ITextRegion region) {
+		int result = -1;
+		if (region != null) {
+			if (fRegions != null) {
+				for (int i = 0; i < fRegions.length; i++) {
+					if (region.equals(fRegions[i])) {
+						result = i;
+						break;
+					}
+				}
+			}
+		}
+		return result;
+	}
+
+	public boolean isEmpty() {
+		return fRegionsCount == 0;
+	}
+
+	public Iterator iterator() {
+		if (size() == 0) {
+			return new NullIterator();
+		} else {
+			return new RegionIterator(toArray());
+		}
+	}
+
+	public ITextRegion remove(int index) {
+		// much more efficient ways to implement this, but
+		// I doubt if called often
+		ITextRegion oneToRemove = get(index);
+		remove(oneToRemove);
+		return oneToRemove;
+	}
+
+	public void remove(ITextRegion a) {
+		if (fRegions == null || a == null)
+			return;
+		int newIndex = 0;
+		ITextRegion[] newRegions = new ITextRegion[fRegionsCount];
+		int oldRegionCount = fRegionsCount;
+		boolean found = false;
+		for (int oldIndex = 0; oldIndex < oldRegionCount; oldIndex++) {
+			ITextRegion candidate = fRegions[oldIndex];
+			if (a == candidate) {
+				fRegionsCount--;
+				found = true;
+			} else
+				newRegions[newIndex++] = fRegions[oldIndex];
+		}
+		if (found)
+			fRegions = newRegions;
+	}
+
+	public void removeAll(ITextRegionList regionList) {
+		// much more efficient ways to implement this, but
+		// I doubt if called often
+		if (regionList != null) {
+			for (int i = 0; i < regionList.size(); i++) {
+				this.remove(regionList.get(i));
+			}
+		}
+
+	}
+
+	public int size() {
+		return fRegionsCount;
+	}
+
+	public ITextRegion[] toArray() {
+		// return "clone" of internal array
+		ITextRegion[] newArray = new ITextRegion[fRegionsCount];
+		System.arraycopy(fRegions, 0, newArray, 0, fRegionsCount);
+		return newArray;
+	}
+	
+	public void trimToSize() {
+		if (fRegions.length > fRegionsCount) {
+			ITextRegion[] newRegions = new ITextRegion[fRegionsCount];
+			System.arraycopy(fRegions, 0, newRegions, 0, fRegionsCount);
+			fRegions = newRegions;
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/IStructuredRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/IStructuredRegion.java
new file mode 100644
index 0000000..f12b76a
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/IStructuredRegion.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text.rules;
+
+import org.eclipse.jface.text.IRegion;
+
+/**
+ * Like super class except allows length and offset to be modified. This is
+ * convenient for some algorithms, and allows region objects to be reused.
+ * Note: There MIGHT be some code that assumes regions are immutable. This
+ * class would not be appropriate for those uses.
+ */
+public interface IStructuredRegion extends IRegion {
+	void setLength(int length);
+
+	void setOffset(int offset);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/IStructuredTypedRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/IStructuredTypedRegion.java
new file mode 100644
index 0000000..1ea21a9
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/IStructuredTypedRegion.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text.rules;
+
+import org.eclipse.jface.text.ITypedRegion;
+
+/**
+ * Similar to extended interface, except it allows the length, offset, and
+ * type to be set. This is useful when iterating through a number of "small"
+ * regions, that all map to the the same partion regions.
+ */
+public interface IStructuredTypedRegion extends IStructuredRegion, ITypedRegion {
+	void setType(String partitionType);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/SimpleStructuredRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/SimpleStructuredRegion.java
new file mode 100644
index 0000000..4ca1ded
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/SimpleStructuredRegion.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text.rules;
+
+import org.eclipse.jface.text.IRegion;
+
+
+
+/**
+ * Similar to jface region except we wanted a setting on length
+ */
+public class SimpleStructuredRegion implements IStructuredRegion {
+	/** The region length */
+	private int fLength;
+
+	/** The region offset */
+	private int fOffset;
+
+	/**
+	 * Create a new region.
+	 * 
+	 * @param offset
+	 *            the offset of the region
+	 * @param length
+	 *            the length of the region
+	 */
+	public SimpleStructuredRegion(int offset, int length) {
+		fOffset = offset;
+		fLength = length;
+	}
+
+	/**
+	 * Two regions are equal if they have the same offset and length.
+	 * 
+	 * @see Object#equals
+	 */
+	public boolean equals(Object o) {
+		if (o instanceof IRegion) {
+			IRegion r = (IRegion) o;
+			return r.getOffset() == fOffset && r.getLength() == fLength;
+		}
+		return false;
+	}
+
+	/*
+	 * @see IRegion#getLength
+	 */
+	public int getLength() {
+		return fLength;
+	}
+
+	/*
+	 * @see IRegion#getOffset
+	 */
+	public int getOffset() {
+		return fOffset;
+	}
+
+	/**
+	 * @see Object#hashCode hascode is overridden since we provide our own
+	 *      equals.
+	 */
+	public int hashCode() {
+		return (fOffset << 24) | (fLength << 16);
+	}
+
+	/**
+	 * Sets the length.
+	 * 
+	 * @param length
+	 *            The length to set
+	 */
+	public void setLength(int length) {
+		fLength = length;
+	}
+
+	public void setOffset(int offset) {
+		fOffset = offset;
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/SimpleStructuredTypedRegion.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/SimpleStructuredTypedRegion.java
new file mode 100644
index 0000000..1822a8a
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/SimpleStructuredTypedRegion.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text.rules;
+
+
+
+
+/**
+ * Similar jace TypedRegion, but had to subclass our version which allowed
+ * length to be set.
+ */
+public class SimpleStructuredTypedRegion extends SimpleStructuredRegion implements IStructuredTypedRegion {
+
+	/** The region's type */
+	private String fType;
+
+	/**
+	 * Creates a typed region based on the given specification.
+	 * 
+	 * @param offset
+	 *            the region's offset
+	 * @param length
+	 *            the region's length
+	 * @param type
+	 *            the region's type
+	 */
+	public SimpleStructuredTypedRegion(int offset, int length, String type) {
+		super(offset, length);
+		fType = type;
+	}
+
+	/**
+	 * Two typed positions are equal if they have the same offset, length, and
+	 * type.
+	 * 
+	 * @see Object#equals
+	 */
+	public boolean equals(Object o) {
+		if (o instanceof SimpleStructuredTypedRegion) {
+			SimpleStructuredTypedRegion r = (SimpleStructuredTypedRegion) o;
+			return super.equals(r) && ((fType == null && r.getType() == null) || fType.equals(r.getType()));
+		}
+		return false;
+	}
+
+	/*
+	 * @see ITypedRegion#getType()
+	 */
+	public String getType() {
+		return fType;
+	}
+
+	/*
+	 * @see Object#hashCode
+	 */
+	public int hashCode() {
+		int type = fType == null ? 0 : fType.hashCode();
+		return super.hashCode() | type;
+	}
+
+	public void setType(String type) {
+		fType = type;
+	}
+
+	/**
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		StringBuffer s = new StringBuffer();
+		s.append(getOffset());
+		s.append(":"); //$NON-NLS-1$
+		s.append(getLength());
+		s.append(" - "); //$NON-NLS-1$
+		s.append(getType());
+		return s.toString();
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/StructuredTextPartitioner.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/StructuredTextPartitioner.java
new file mode 100644
index 0000000..445e5f2
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/rules/StructuredTextPartitioner.java
@@ -0,0 +1,655 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2011 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.text.rules;
+
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.wst.sse.core.internal.ltk.parser.IBlockedStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.parser.ForeignRegion;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextPartitioner;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionCollection;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+import org.eclipse.wst.sse.core.text.IStructuredPartitions;
+
+
+/**
+ * Base Document partitioner for StructuredDocuments. BLOCK_TEXT ITextRegions
+ * have a partition type of BLOCK or BLOCK:TAGNAME if a surrounding tagname
+ * was recorded.
+ * 
+ * Subclasses should synchronize access to <code>internalReusedTempInstance</code> using the lock
+ * <code>PARTITION_LOCK</code>.
+ */
+public class StructuredTextPartitioner implements IDocumentPartitioner, IStructuredTextPartitioner {
+
+	static class CachedComputedPartitions {
+		int fLength;
+		int fOffset;
+		ITypedRegion[] fPartitions;
+		boolean isInValid;
+
+		CachedComputedPartitions(int offset, int length, ITypedRegion[] partitions) {
+			fOffset = offset;
+			fLength = length;
+			fPartitions = partitions;
+			isInValid = true;
+		}
+	}
+
+	private CachedComputedPartitions cachedPartitions = new CachedComputedPartitions(-1, -1, null);
+	protected String[] fSupportedTypes = null;
+	protected IStructuredTypedRegion internalReusedTempInstance = new SimpleStructuredTypedRegion(0, 0, IStructuredPartitions.DEFAULT_PARTITION);
+	protected IStructuredDocument fStructuredDocument;
+
+	protected final Object PARTITION_LOCK = new Object();
+
+	/**
+	 * StructuredTextPartitioner constructor comment.
+	 */
+	public StructuredTextPartitioner() {
+		super();
+	}
+
+	/**
+	 * Returns the partitioning of the given range of the connected document.
+	 * There must be a document connected to this partitioner.
+	 * 
+	 * Note: this shouldn't be called directly by clients, unless they control
+	 * the threading that includes modifications to the document. Otherwise
+	 * the document could be modified while partitions are being computed. We
+	 * advise that clients use the computePartitions API directly from the
+	 * document, so they won't have to worry about that.
+	 * 
+	 * @param offset
+	 *            the offset of the range of interest
+	 * @param length
+	 *            the length of the range of interest
+	 * @return the partitioning of the range
+	 */
+	public ITypedRegion[] computePartitioning(int offset, int length) {
+		if (fStructuredDocument == null) {
+			throw new IllegalStateException("document partitioner is not connected"); //$NON-NLS-1$
+		}
+		ITypedRegion[] results = null;
+
+		synchronized (cachedPartitions) {
+			if ((!cachedPartitions.isInValid) && (offset == cachedPartitions.fOffset) && (length == cachedPartitions.fLength))
+				results = cachedPartitions.fPartitions;
+		}
+
+		if (results == null) {
+			if (length == 0) {
+				results = new ITypedRegion[]{getPartition(offset)};
+			} else {
+				List list = new ArrayList();
+				int endPos = offset + length;
+				if (endPos > fStructuredDocument.getLength()) {
+					// This can occur if the model instance is being
+					// changed
+					// and everyone's not yet up to date
+					return new ITypedRegion[]{createPartition(offset, length, getUnknown())};
+				}
+				int currentPos = offset;
+				IStructuredTypedRegion previousPartition = null;
+				while (currentPos < endPos) {
+					IStructuredTypedRegion partition = null;
+					synchronized (PARTITION_LOCK) {
+						internalGetPartition(currentPos, false);
+						currentPos += internalReusedTempInstance.getLength();
+						
+						// check if this partition just continues last one
+						// (type is the same),
+						// if so, just extend length of last one, not need to
+						// create new
+						// instance.
+						if (previousPartition != null && internalReusedTempInstance.getType().equals(previousPartition.getType())) {
+							// same partition type
+							previousPartition.setLength(previousPartition.getLength() + internalReusedTempInstance.getLength());
+						}
+						else {
+							// not the same, so add to list
+							partition = createNewPartitionInstance();
+						}
+					}
+					if (partition != null) {
+						list.add(partition);
+						// and make current, previous
+						previousPartition = partition;
+					}
+				}
+				results = new ITypedRegion[list.size()];
+				list.toArray(results);
+			}
+			if (results.length > 0) {
+				// truncate returned results to requested range
+				if (results[0].getOffset() < offset && results[0] instanceof IStructuredRegion) {
+					((IStructuredRegion) results[0]).setOffset(offset);
+				}
+				int lastEnd = results[results.length - 1].getOffset() + results[results.length - 1].getLength();
+				if (lastEnd > offset + length && results[results.length - 1] instanceof IStructuredRegion) {
+					((IStructuredRegion) results[results.length - 1]).setLength(offset + length - results[results.length - 1].getOffset());
+				}
+			}
+			synchronized (cachedPartitions) {
+				cachedPartitions.fLength = length;
+				cachedPartitions.fOffset = offset;
+				cachedPartitions.fPartitions = results;
+				cachedPartitions.isInValid = false;
+			}
+		}
+		return results;
+	}
+
+	private void invalidatePartitionCache() {
+		synchronized (cachedPartitions) {
+			cachedPartitions.isInValid = true;
+		}
+	}
+
+	/**
+	 * Connects the document to the partitioner, i.e. indicates the begin of
+	 * the usage of the receiver as partitioner of the given document.
+	 */
+	public synchronized void connect(IDocument document) {
+		if (document instanceof IStructuredDocument) {
+			invalidatePartitionCache();
+			this.fStructuredDocument = (IStructuredDocument) document;
+		} else {
+			throw new IllegalArgumentException("This class and API are for Structured Documents only"); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Determines if the given ITextRegionContainer itself contains another
+	 * ITextRegionContainer
+	 * 
+	 * @param ITextRegionContainer
+	 * @return boolean
+	 */
+	protected boolean containsEmbeddedRegion(IStructuredDocumentRegion container) {
+		boolean containsEmbeddedRegion = false;
+
+		ITextRegionList regions = container.getRegions();
+		for (int i = 0; i < regions.size(); i++) {
+			ITextRegion region = regions.get(i);
+			if (region instanceof ITextRegionContainer) {
+				containsEmbeddedRegion = true;
+				break;
+			}
+		}
+		return containsEmbeddedRegion;
+	}
+
+	private IStructuredTypedRegion createNewPartitionInstance() {
+		synchronized (PARTITION_LOCK) {
+			return new SimpleStructuredTypedRegion(internalReusedTempInstance.getOffset(), internalReusedTempInstance.getLength(), internalReusedTempInstance.getType());
+		}
+	}
+
+	/**
+	 * Creates the concrete partition from the given values. Returns a new
+	 * instance for each call.
+	 * 
+	 * Subclasses may override.
+	 * 
+	 * @param offset
+	 * @param length
+	 * @param type
+	 * @return ITypedRegion
+	 * 
+	 * TODO: should be protected
+	 */
+	public IStructuredTypedRegion createPartition(int offset, int length, String type) {
+		return new SimpleStructuredTypedRegion(offset, length, type);
+	}
+
+	/**
+	 * Disconnects the document from the partitioner, i.e. indicates the end
+	 * of the usage of the receiver as partitioner of the given document.
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentPartitioner#disconnect()
+	 */
+	public synchronized void disconnect() {
+		invalidatePartitionCache();
+		this.fStructuredDocument = null;
+	}
+
+	/**
+	 * Informs about a forthcoming document change.
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentPartitioner#documentAboutToBeChanged(DocumentEvent)
+	 */
+	public void documentAboutToBeChanged(DocumentEvent event) {
+		invalidatePartitionCache();
+	}
+
+	/**
+	 * The document has been changed. The partitioner updates the set of
+	 * regions and returns whether the structure of the document partitioning
+	 * has been changed, i.e. whether partitions have been added or removed.
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentPartitioner#documentChanged(DocumentEvent)
+	 */
+	public boolean documentChanged(DocumentEvent event) {
+		boolean result = false;
+		if (event instanceof StructuredDocumentRegionsReplacedEvent) {
+			// partitions don't always change while document regions do,
+			// but that's the only "quick check" we have.
+			// I'm not sure if something more sophisticated will be needed
+			// in the future. (dmw, 02/18/04).
+			result = true;
+		}
+		return result;
+	}
+
+	protected boolean doParserSpecificCheck(int offset, boolean partitionFound, IStructuredDocumentRegion sdRegion, IStructuredDocumentRegion previousStructuredDocumentRegion, ITextRegion next, ITextRegion previousStart) {
+		// this (conceptually) abstract method is not concerned with
+		// specific region types
+		return false;
+	}
+
+	protected IStructuredDocumentRegion getParserSpecificPreviousRegion(IStructuredDocumentRegion currentRegion) {
+		return currentRegion != null ? currentRegion.getPrevious() : null;
+	}
+
+	/**
+	 * Returns the content type of the partition containing the given
+	 * character position of the given document. The document has previously
+	 * been connected to the partitioner.
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentPartitioner#getContentType(int)
+	 */
+	public String getContentType(int offset) {
+		return getPartition(offset).getType();
+	}
+
+	/**
+	 * To be used by default!
+	 */
+	public String getDefaultPartitionType() {
+
+		return IStructuredPartitions.DEFAULT_PARTITION;
+	}
+
+	/**
+	 * Returns the set of all possible content types the partitioner supports.
+	 * I.e. Any result delivered by this partitioner may not contain a content
+	 * type which would not be included in this method's result.
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentPartitioner#getLegalContentTypes()
+	 */
+	public java.lang.String[] getLegalContentTypes() {
+		if (fSupportedTypes == null) {
+			initLegalContentTypes();
+		}
+		return fSupportedTypes;
+	}
+
+	/**
+	 * Returns the partition containing the given character position of the
+	 * given document. The document has previously been connected to the
+	 * partitioner.
+	 * 
+	 * Note: this shouldn't be called directly by clients, unless they control
+	 * the threading that includes modifications to the document. Otherwise
+	 * the document could be modified while partitions are being computed. We
+	 * advise that clients use the getPartition API directly from the
+	 * document, so they won't have to worry about that.
+	 * 
+	 * 
+	 * 
+	 * @see org.eclipse.jface.text.IDocumentPartitioner#getPartition(int)
+	 */
+	public ITypedRegion getPartition(int offset) {
+		internalGetPartition(offset, true);
+		return createNewPartitionInstance();
+	}
+
+	protected String getPartitionFromBlockedText(ITextRegion region, int offset, String result) {
+		// parser sensitive code was moved to subclass for quick transition
+		// this (conceptually) abstract version isn't concerned with blocked
+		// text
+
+		return result;
+	}
+
+	protected String getPartitionType(ForeignRegion region, int offset) {
+		String tagname = region.getSurroundingTag();
+		String result = null;
+		if (tagname != null) {
+			result = "BLOCK:" + tagname.toUpperCase(Locale.ENGLISH); //$NON-NLS-1$
+		} else {
+			result = "BLOCK"; //$NON-NLS-1$
+		}
+		return result;
+	}
+
+
+	protected String getPartitionType(IBlockedStructuredDocumentRegion blockedStructuredDocumentRegion, int offset) {
+		String result = null;
+		ITextRegionList regions = blockedStructuredDocumentRegion.getRegions();
+
+		// regions should never be null, or hold zero regions, but just in
+		// case...
+		if (regions != null && regions.size() > 0) {
+			if (regions.size() == 1) {
+				// if only one, then its a "pure" blocked note.
+				// if more than one, then must contain some embedded region
+				// container
+				ITextRegion blockedRegion = regions.get(0);
+				// double check for code safefy, though should always be true
+				if (blockedRegion instanceof ForeignRegion) {
+					result = getPartitionType((ForeignRegion) blockedRegion, offset);
+				}
+			} else {
+				// must have some embedded region container, so we'll make
+				// sure we'll get the appropriate one
+				result = getReleventRegionType(blockedStructuredDocumentRegion, offset);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Method getPartitionType.
+	 * 
+	 * @param region
+	 * @return String
+	 */
+	private String getPartitionType(ITextRegion region) {
+		// if it get's to this "raw" level, then
+		// must be default.
+		return getDefaultPartitionType();
+	}
+
+	/**
+	 * Returns the partition based on region type. This basically maps from
+	 * one region-type space to another, higher level, region-type space.
+	 * 
+	 * @param region
+	 * @param offset
+	 * @return String
+	 */
+	public String getPartitionType(ITextRegion region, int offset) {
+		String result = getDefaultPartitionType();
+		//		if (region instanceof ContextRegionContainer) {
+		//			result = getPartitionType((ITextRegionContainer) region, offset);
+		//		} else {
+		if (region instanceof ITextRegionContainer) {
+			result = getPartitionType((ITextRegionContainer) region, offset);
+		}
+
+		result = getPartitionFromBlockedText(region, offset, result);
+
+		return result;
+
+	}
+
+	/**
+	 * Similar to method with 'ITextRegion' as argument, except for
+	 * RegionContainers, if it has embedded regions, then we need to drill
+	 * down and return DocumentPartition based on "lowest level" region type.
+	 * For example, in <body id=" <%= object.getID() %>" > The text between
+	 * <%= and %> would be a "java region" not an "HTML region".
+	 */
+	protected String getPartitionType(ITextRegionContainer region, int offset) {
+		// TODO this method needs to be 'cleaned up' after refactoring
+		// its instanceof logic seems messed up now.
+		String result = null;
+		if (region != null) {
+			ITextRegion coreRegion = region;
+			if (coreRegion instanceof ITextRegionContainer) {
+				result = getPartitionType((ITextRegionContainer) coreRegion, ((ITextRegionContainer) coreRegion).getRegions(), offset);
+			} else {
+				result = getPartitionType(region);
+			}
+		} else {
+			result = getPartitionType((ITextRegion) region, offset);
+		}
+
+		return result;
+	}
+
+	private String getPartitionType(ITextRegionContainer coreRegion, ITextRegionList regions, int offset) {
+		String result = null;
+		for (int i = 0; i < regions.size(); i++) {
+			ITextRegion region = regions.get(i);
+			if (coreRegion.containsOffset(region, offset)) {
+				result = getPartitionType(region, offset);
+				break;
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Computes the partition type for the zero-length partition between a
+	 * start tag and end tag with the given name regions.
+	 * 
+	 * @param previousStartTagNameRegion
+	 * @param nextEndTagNameRegion
+	 * @return String
+	 */
+	public String getPartitionTypeBetween(IStructuredDocumentRegion previousNode, IStructuredDocumentRegion nextNode) {
+		return getDefaultPartitionType();
+	}
+
+	/**
+	 * Return the ITextRegion at the given offset. For most cases, this will
+	 * be the flatNode itself. Should it contain an embedded
+	 * ITextRegionContainer, will return the internal region at the offset
+	 * 
+	 * 
+	 * @param flatNode
+	 * @param offset
+	 * @return ITextRegion
+	 */
+	private String getReleventRegionType(IStructuredDocumentRegion flatNode, int offset) {
+		//		* Note: the original form of this method -- which returned "deep"
+		// region, isn't that
+		//		* useful, after doing parent elimination refactoring,
+		//		* since once the deep region is returned, its hard to get its text
+		// or offset without
+		//		* proper parent.
+		ITextRegion resultRegion = null;
+		if (containsEmbeddedRegion(flatNode)) {
+			resultRegion = flatNode.getRegionAtCharacterOffset(offset);
+			if (resultRegion instanceof ITextRegionContainer) {
+				resultRegion = flatNode.getRegionAtCharacterOffset(offset);
+				ITextRegionList regions = ((ITextRegionContainer) resultRegion).getRegions();
+				for (int i = 0; i < regions.size(); i++) {
+					ITextRegion region = regions.get(i);
+					if (flatNode.getStartOffset(region) <= offset && offset < flatNode.getEndOffset(region)) {
+						resultRegion = region;
+						break;
+					}
+				}
+			}
+		} else {
+			resultRegion = flatNode;
+		}
+		return resultRegion.getType();
+	}
+
+	/**
+	 * To be used, instead of default, when there is some thing surprising
+	 * about are attempt to partition
+	 */
+	protected String getUnknown() {
+		return IStructuredPartitions.UNKNOWN_PARTITION;
+	}
+
+	/**
+	 * to be abstract eventually
+	 */
+	protected void initLegalContentTypes() {
+		fSupportedTypes = new String[]{IStructuredPartitions.DEFAULT_PARTITION, IStructuredPartitions.UNKNOWN_PARTITION};
+	}
+
+	/**
+	 * Returns the partition containing the given character position of the
+	 * given document. The document has previously been connected to the
+	 * partitioner. If the checkBetween parameter is true, an offset between a
+	 * start and end tag will return a zero-length region.
+	 */
+	private void internalGetPartition(int offset, boolean checkBetween) {
+		if (fStructuredDocument == null) {
+			throw new IllegalStateException("document partitioner is not connected"); //$NON-NLS-1$
+		}
+
+		boolean partitionFound = false;
+		int docLength = fStructuredDocument.getLength();
+		// get document region type and map to partition type :
+		// Note: a partion can be smaller than a flatnode, if that flatnode
+		// contains a region container.
+		// That's why we need to get "relevent region".
+		IStructuredDocumentRegion structuredDocumentRegion = fStructuredDocument.getRegionAtCharacterOffset(offset);
+		// flatNode is null if empty document
+		// this is king of a "normal case" for empty document
+		if (structuredDocumentRegion == null) {
+			if (docLength == 0) {
+				/*
+				 * In order to prevent infinite error loops, this partition
+				 * must never have a zero length unless the document is also
+				 * zero length
+				 */
+				setInternalPartition(offset, 0, getDefaultPartitionType());
+				partitionFound = true;
+			}
+			else {
+				/*
+				 * This case is "unusual". When would region be null, and
+				 * document longer than 0. I think this means something's "out
+				 * of sync". And we may want to "flag" that fact and just
+				 * return one big region of 'unknown', instead of one
+				 * character at a time.
+				 */
+				setInternalPartition(offset, 1, getUnknown());
+				partitionFound = true;
+			}
+		}	
+		else if (checkBetween) {
+			// dmw: minimizes out to the first if test above
+			//			if (structuredDocumentRegion == null && docLength == 0) {
+			//				// known special case for an empty document
+			//				setInternalPartition(offset, 0, getDefault());
+			//				partitionFound = true;
+			//			}
+			//			else
+			if (structuredDocumentRegion.getStartOffset() == offset) {
+				IStructuredDocumentRegion previousStructuredDocumentRegion = getParserSpecificPreviousRegion(structuredDocumentRegion);
+				if (previousStructuredDocumentRegion != null) {
+					ITextRegion next = structuredDocumentRegion.getRegionAtCharacterOffset(offset);
+					ITextRegion previousStart = previousStructuredDocumentRegion.getRegionAtCharacterOffset(previousStructuredDocumentRegion.getStartOffset());
+					partitionFound = doParserSpecificCheck(offset, partitionFound, structuredDocumentRegion, previousStructuredDocumentRegion, next, previousStart);
+				}
+			}
+		}
+
+		if (!partitionFound && structuredDocumentRegion != null) {
+			/* We want the actual ITextRegion and not a possible ITextRegionCollection that
+			 * could be returned by IStructuredDocumentRegion#getRegionAtCharacterOffset
+			 * This allows for correct syntax highlighting and content assist.
+			 */
+			DeepRegion resultRegion = getDeepRegionAtCharacterOffset(structuredDocumentRegion, offset);
+			partitionFound = isDocumentRegionBasedPartition(structuredDocumentRegion, resultRegion.region, offset);
+			if (!partitionFound) {
+				if (resultRegion.region != null) {
+					String type = getPartitionType(resultRegion.region, offset);
+					setInternalPartition(offset, resultRegion.end - offset, type);
+				} else {
+					// can happen at EOF
+					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=224886
+					// The unknown type was causing problems with content assist in JSP documents
+					setInternalPartition(offset, 1, getDefaultPartitionType());
+				}
+			}
+		}
+	}
+
+	private static class DeepRegion {
+		int end;
+		ITextRegion region;
+		DeepRegion(ITextRegion r, int e) {
+			region = r;
+			end = e;
+		}
+	}
+
+	/**
+	 * <p>Unlike {@link IStructuredDocumentRegion#getRegionAtCharacterOffset(int)} this will dig
+	 * into <code>ITextRegionCollection</code> to find the region containing the given offset</p>
+	 * 
+	 * @param region the containing region of the given <code>offset</code>
+	 * @param offset to the overall offset in the document.
+	 * @return the <code>ITextRegion</code> containing the given <code>offset</code>, will never be
+	 * a <code>ITextRegionCollextion</code>
+	 */
+	private DeepRegion getDeepRegionAtCharacterOffset(IStructuredDocumentRegion region, int offset) {
+		ITextRegion text = region.getRegionAtCharacterOffset(offset);
+		int end = region.getStartOffset();
+		if (text != null)
+			end += text.getStart();
+		while (text instanceof ITextRegionCollection) {
+			text = ((ITextRegionCollection) text).getRegionAtCharacterOffset(offset);
+			end += text.getStart();
+		}
+		if (text != null)
+			end += text.getLength();
+		return new DeepRegion(text, end);
+	}
+
+	/**
+	 * Provides for a per-StructuredDocumentRegion override selecting the
+	 * partition type using more than just a single ITextRegion.
+	 * 
+	 * @param structuredDocumentRegion
+	 *            the StructuredDocumentRegion
+	 * @param containedChildRegion
+	 *            an ITextRegion within the given StructuredDocumentRegion
+	 *            that would normally determine the partition type by itself
+	 * @param offset
+	 *            the document offset
+	 * @return true if the partition type will be overridden, false to
+	 *         continue normal processing
+	 */
+	protected boolean isDocumentRegionBasedPartition(IStructuredDocumentRegion structuredDocumentRegion, ITextRegion containedChildRegion, int offset) {
+		return false;
+	}
+
+	public IDocumentPartitioner newInstance() {
+		return new StructuredTextPartitioner();
+	}
+
+	protected void setInternalPartition(int offset, int length, String type) {
+		synchronized (PARTITION_LOCK) {
+			internalReusedTempInstance.setOffset(offset);
+			internalReusedTempInstance.setLength(length);
+			internalReusedTempInstance.setType(type);
+		}
+	}
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/CommandCursorPosition.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/CommandCursorPosition.java
new file mode 100644
index 0000000..439cf52
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/CommandCursorPosition.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.undo;
+
+
+
+public interface CommandCursorPosition {
+
+	/**
+	 * Returns the cursor position to be set to after this command is redone.
+	 * 
+	 * @return int
+	 */
+	int getRedoCursorPosition();
+
+	/**
+	 * Returns the length of text to be selected after this command is redone.
+	 * 
+	 * @return int
+	 */
+	int getRedoSelectionLength();
+
+	/**
+	 * Returns the cursor position to be set to after this command is undone.
+	 * 
+	 * @return int
+	 */
+	int getUndoCursorPosition();
+
+	/**
+	 * Returns the length of text to be selected after this command is undone.
+	 * 
+	 * @return int
+	 */
+	int getUndoSelectionLength();
+
+	/**
+	 * Sets the cursor position to be used after this command is redone.
+	 */
+	void setRedoCursorPosition(int cursorPosition);
+
+	/**
+	 * Sets the length of text to be selected after this command is redone.
+	 */
+	void setRedoSelectionLength(int selectionLength);
+
+	/**
+	 * Sets the cursor position to be used after this command is undone.
+	 */
+	void setUndoCursorPosition(int cursorPosition);
+
+	/**
+	 * Sets the length of text to be selected after this command is undone.
+	 */
+	void setUndoSelectionLength(int selectionLength);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/IDocumentSelectionMediator.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/IDocumentSelectionMediator.java
new file mode 100644
index 0000000..5632884
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/IDocumentSelectionMediator.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.undo;
+
+import org.eclipse.jface.text.IDocument;
+
+
+public interface IDocumentSelectionMediator {
+	/**
+	 * Returns the document selection mediator's input document.
+	 * 
+	 * @return the document selection mediator's input document
+	 */
+	IDocument getDocument();
+
+	/**
+	 * Sets a new selection in the document as a result of an undo operation.
+	 * 
+	 * UndoDocumentEvent contains the requester of the undo operation, and the
+	 * offset and length of the new selection. Implementation of
+	 * IDocumentSelectionMediator can check if it's the requester that caused
+	 * the new selection, and decide if the new selection should be applied.
+	 */
+	void undoOperationSelectionChanged(UndoDocumentEvent event);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/IStructuredTextUndoManager.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/IStructuredTextUndoManager.java
new file mode 100644
index 0000000..80351ba
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/IStructuredTextUndoManager.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.undo;
+
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CommandStack;
+
+public interface IStructuredTextUndoManager {
+
+	/**
+	 * Begin recording undo transactions.
+	 */
+	void beginRecording(Object requester);
+
+	/**
+	 * Begin recording undo transactions.
+	 */
+	void beginRecording(Object requester, int cursorPosition, int selectionLength);
+
+	/**
+	 * Begin recording undo transactions.
+	 */
+	void beginRecording(Object requester, String label);
+
+	/**
+	 * Begin recording undo transactions.
+	 */
+	void beginRecording(Object requester, String label, int cursorPosition, int selectionLength);
+
+	/**
+	 * Begin recording undo transactions.
+	 */
+	void beginRecording(Object requester, String label, String description);
+
+	/**
+	 * Begin recording undo transactions.
+	 */
+	void beginRecording(Object requester, String label, String description, int cursorPosition, int selectionLength);
+
+	/**
+	 * Connect the mediator to the undo manager.
+	 */
+	void connect(IDocumentSelectionMediator mediator);
+
+	/**
+	 * Disable undo management.
+	 */
+	void disableUndoManagement();
+
+	/**
+	 * Disconnect the mediator from the undo manager.
+	 */
+	void disconnect(IDocumentSelectionMediator mediator);
+
+	/**
+	 * Enable undo management.
+	 */
+	void enableUndoManagement();
+
+	/**
+	 * End recording undo transactions.
+	 */
+	void endRecording(Object requester);
+
+	/**
+	 * End recording undo transactions.
+	 */
+	void endRecording(Object requester, int cursorPosition, int selectionLength);
+
+	/**
+	 * <p>
+	 * Normally, the undo manager can figure out the best times when to end a
+	 * pending command and begin a new one ... to the structure of a structued
+	 * document. There are times, however, when clients may wish to override
+	 * those algorithms and end one earlier than normal. The one known case is
+	 * for multipage editors. If a user is on one page, and type '123' as
+	 * attribute value, then click around to other parts of page, or different
+	 * pages, then return to '123|' and type 456, then "undo" they typically
+	 * expect the undo to just undo what they just typed, the 456, not the
+	 * whole attribute value.
+	 * <p>
+	 * If there is no pending command, the request is ignored.
+	 */
+	public void forceEndOfPendingCommand(Object requester, int currentPosition, int length);
+
+	/**
+	 * Some clients need to do complicated things with undo stack. Plus, in
+	 * some cases, if clients setCommandStack temporarily, they have
+	 * reponsibility to set back to original one when finished.
+	 */
+	public CommandStack getCommandStack();
+
+	/**
+	 * Get the redo command even if it's not committed yet.
+	 */
+	Command getRedoCommand();
+
+	/**
+	 * Get the undo command even if it's not committed yet.
+	 */
+	Command getUndoCommand();
+
+	/**
+	 * Redo the last command in the undo manager.
+	 */
+	void redo();
+
+	/**
+	 * Redo the last command in the undo manager and notify the requester
+	 * about the new selection.
+	 */
+	void redo(IDocumentSelectionMediator requester);
+
+	/**
+	 * Returns whether at least one text change can be repeated. A text change
+	 * can be repeated only if it was executed and rolled back.
+	 * 
+	 * @return <code>true</code> if at least on text change can be repeated
+	 */
+	boolean redoable();
+
+	/**
+	 * Set the command stack.
+	 */
+	void setCommandStack(CommandStack commandStack);
+
+	/**
+	 * Undo the last command in the undo manager.
+	 */
+	void undo();
+
+	/**
+	 * Undo the last command in the undo manager and notify the requester
+	 * about the new selection.
+	 */
+	void undo(IDocumentSelectionMediator requester);
+
+	/**
+	 * Returns whether at least one text change can be rolled back.
+	 * 
+	 * @return <code>true</code> if at least one text change can be rolled
+	 *         back
+	 */
+	boolean undoable();
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/StructuredTextCommand.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/StructuredTextCommand.java
new file mode 100644
index 0000000..b085f5b
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/StructuredTextCommand.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.undo;
+
+
+
+public interface StructuredTextCommand {
+
+	String getTextDeleted();
+
+	int getTextEnd();
+
+	String getTextInserted();
+
+	int getTextStart();
+
+	void setTextDeleted(String textDeleted);
+
+	void setTextEnd(int textEnd);
+
+	void setTextInserted(String textInserted);
+
+	void setTextStart(int textStart);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/StructuredTextCommandImpl.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/StructuredTextCommandImpl.java
new file mode 100644
index 0000000..70f2bc2
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/StructuredTextCommandImpl.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.undo;
+
+
+
+import org.eclipse.emf.common.command.AbstractCommand;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+
+
+public class StructuredTextCommandImpl extends AbstractCommand implements StructuredTextCommand {
+
+	protected IDocument fDocument = null; // needed for updating the text
+	protected String fTextDeleted = null;
+	protected int fTextEnd = -1;
+	protected String fTextInserted = null;
+	protected int fTextStart = -1;
+
+	/**
+	 * We have no-arg constructor non-public to force document to be specfied.
+	 *  
+	 */
+	protected StructuredTextCommandImpl() {
+		super();
+	}
+
+	public StructuredTextCommandImpl(IDocument document) {
+		this();
+		fDocument = document; // needed for updating the text
+	}
+
+	public void execute() {
+	}
+
+	/**
+	 * getTextDeleted method comment.
+	 */
+	public java.lang.String getTextDeleted() {
+		return fTextDeleted;
+	}
+
+	/**
+	 * textEnd is the same as (textStart + textInserted.length())
+	 */
+	public int getTextEnd() {
+		return fTextEnd;
+	}
+
+	/**
+	 * getTextInserted method comment.
+	 */
+	public java.lang.String getTextInserted() {
+		return fTextInserted;
+	}
+
+	/**
+	 * getTextStart method comment.
+	 */
+	public int getTextStart() {
+		return fTextStart;
+	}
+
+	protected boolean prepare() {
+		return true;
+	}
+
+	public void redo() {
+		if (fDocument instanceof IStructuredDocument) {
+			// note: one of the few places we programatically ignore read-only
+			// settings
+			((IStructuredDocument) fDocument).replaceText(this, fTextStart, fTextDeleted.length(), fTextInserted, true);
+		} else {
+			try {
+				fDocument.replace(fTextStart, fTextDeleted.length(), fTextInserted);
+			} catch (BadLocationException e) {
+				// assumed impossible, for now
+				Logger.logException(e);
+			}
+		}
+	}
+
+	/**
+	 * setTextDeleted method comment.
+	 */
+	public void setTextDeleted(java.lang.String textDeleted) {
+		fTextDeleted = textDeleted;
+	}
+
+	/**
+	 * setTextEnd method comment.
+	 */
+	public void setTextEnd(int textEnd) {
+		fTextEnd = textEnd;
+	}
+
+	/**
+	 * setTextInserted method comment.
+	 */
+	public void setTextInserted(java.lang.String textInserted) {
+		fTextInserted = textInserted;
+	}
+
+	/**
+	 * setTextStart method comment.
+	 */
+	public void setTextStart(int textStart) {
+		fTextStart = textStart;
+	}
+
+	public void undo() {
+		if (fDocument instanceof IStructuredDocument) {
+			// note: one of the few places we programatically ignore read-only
+			// settings
+			((IStructuredDocument) fDocument).replaceText(this, fTextStart, fTextInserted.length(), fTextDeleted, true);
+		} else {
+			try {
+				fDocument.replace(fTextStart, fTextInserted.length(), fTextDeleted);
+			} catch (BadLocationException e) {
+				// assumed impossible, for now
+				Logger.logException(e);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/StructuredTextCompoundCommandImpl.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/StructuredTextCompoundCommandImpl.java
new file mode 100644
index 0000000..ddf7636
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/StructuredTextCompoundCommandImpl.java
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.undo;
+
+
+
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+
+
+
+public class StructuredTextCompoundCommandImpl extends CompoundCommand implements CommandCursorPosition {
+	protected int fRedoCursorPosition = -1;
+	protected int fRedoSelectionLength = 0;
+
+	protected int fUndoCursorPosition = -1;
+	protected int fUndoSelectionLength = 0;
+
+	/**
+	 * StructuredTextCompoundCommandImpl constructor comment.
+	 */
+	public StructuredTextCompoundCommandImpl() {
+		super();
+	}
+
+	/**
+	 * StructuredTextCompoundCommandImpl constructor comment.
+	 * 
+	 * @param resultIndex
+	 *            int
+	 */
+	public StructuredTextCompoundCommandImpl(int resultIndex) {
+		super(resultIndex);
+	}
+
+	/**
+	 * StructuredTextCompoundCommandImpl constructor comment.
+	 * 
+	 * @param resultIndex
+	 *            int
+	 * @param commandList
+	 *            java.util.List
+	 */
+	public StructuredTextCompoundCommandImpl(int resultIndex, java.util.List commandList) {
+		super(resultIndex, commandList);
+	}
+
+	/**
+	 * StructuredTextCompoundCommandImpl constructor comment.
+	 * 
+	 * @param resultIndex
+	 *            int
+	 * @param label
+	 *            java.lang.String
+	 */
+	public StructuredTextCompoundCommandImpl(int resultIndex, String label) {
+		super(resultIndex, label);
+	}
+
+	/**
+	 * StructuredTextCompoundCommandImpl constructor comment.
+	 * 
+	 * @param resultIndex
+	 *            int
+	 * @param label
+	 *            java.lang.String
+	 * @param commandList
+	 *            java.util.List
+	 */
+	public StructuredTextCompoundCommandImpl(int resultIndex, String label, java.util.List commandList) {
+		super(resultIndex, label, commandList);
+	}
+
+	/**
+	 * StructuredTextCompoundCommandImpl constructor comment.
+	 * 
+	 * @param resultIndex
+	 *            int
+	 * @param label
+	 *            java.lang.String
+	 * @param description
+	 *            java.lang.String
+	 */
+	public StructuredTextCompoundCommandImpl(int resultIndex, String label, String description) {
+		super(resultIndex, label, description);
+	}
+
+	/**
+	 * StructuredTextCompoundCommandImpl constructor comment.
+	 * 
+	 * @param resultIndex
+	 *            int
+	 * @param label
+	 *            java.lang.String
+	 * @param description
+	 *            java.lang.String
+	 * @param commandList
+	 *            java.util.List
+	 */
+	public StructuredTextCompoundCommandImpl(int resultIndex, String label, String description, java.util.List commandList) {
+		super(resultIndex, label, description, commandList);
+	}
+
+	/**
+	 * StructuredTextCompoundCommandImpl constructor comment.
+	 * 
+	 * @param commandList
+	 *            java.util.List
+	 */
+	public StructuredTextCompoundCommandImpl(java.util.List commandList) {
+		super(commandList);
+	}
+
+	/**
+	 * StructuredTextCompoundCommandImpl constructor comment.
+	 * 
+	 * @param label
+	 *            java.lang.String
+	 */
+	public StructuredTextCompoundCommandImpl(String label) {
+		super(label);
+	}
+
+	/**
+	 * StructuredTextCompoundCommandImpl constructor comment.
+	 * 
+	 * @param label
+	 *            java.lang.String
+	 * @param commandList
+	 *            java.util.List
+	 */
+	public StructuredTextCompoundCommandImpl(String label, java.util.List commandList) {
+		super(label, commandList);
+	}
+
+	/**
+	 * StructuredTextCompoundCommandImpl constructor comment.
+	 * 
+	 * @param label
+	 *            java.lang.String
+	 * @param description
+	 *            java.lang.String
+	 */
+	public StructuredTextCompoundCommandImpl(String label, String description) {
+		super(label, description);
+	}
+
+	/**
+	 * StructuredTextCompoundCommandImpl constructor comment.
+	 * 
+	 * @param label
+	 *            java.lang.String
+	 * @param description
+	 *            java.lang.String
+	 * @param commandList
+	 *            java.util.List
+	 */
+	public StructuredTextCompoundCommandImpl(String label, String description, java.util.List commandList) {
+		super(label, description, commandList);
+	}
+
+	/**
+	 * Returns the cursor position to be set to after this command is redone.
+	 * 
+	 * @return int
+	 */
+	public int getRedoCursorPosition() {
+		int cursorPosition = -1;
+
+		if (fRedoCursorPosition != -1)
+			cursorPosition = fRedoCursorPosition;
+		else if (!commandList.isEmpty()) {
+			int commandListSize = commandList.size();
+			Command lastCommand = (Command) commandList.get(commandListSize - 1);
+
+			if (lastCommand instanceof CommandCursorPosition)
+				cursorPosition = ((CommandCursorPosition) lastCommand).getRedoCursorPosition();
+		}
+
+		return cursorPosition;
+	}
+
+	/**
+	 * Returns the length of text to be selected after this command is redone.
+	 * 
+	 * @return int
+	 */
+	public int getRedoSelectionLength() {
+		return fRedoSelectionLength;
+	}
+
+	/**
+	 * Returns the cursor position to be set to after this command is undone.
+	 * 
+	 * @return int
+	 */
+	public int getUndoCursorPosition() {
+		int cursorPosition = -1;
+
+		if (fUndoCursorPosition != -1)
+			cursorPosition = fUndoCursorPosition;
+		else if (!commandList.isEmpty()) {
+			// never used
+			//int commandListSize = commandList.size();
+			Command firstCommand = (Command) commandList.get(0);
+
+			if (firstCommand instanceof CommandCursorPosition)
+				cursorPosition = ((CommandCursorPosition) firstCommand).getUndoCursorPosition();
+		}
+
+		return cursorPosition;
+	}
+
+	/**
+	 * Returns the length of text to be selected after this command is undone.
+	 * 
+	 * @return int
+	 */
+	public int getUndoSelectionLength() {
+		return fUndoSelectionLength;
+	}
+
+	/**
+	 * Sets the cursor position to be used after this command is redone.
+	 */
+	public void setRedoCursorPosition(int cursorPosition) {
+		fRedoCursorPosition = cursorPosition;
+	}
+
+	/**
+	 * Sets the length of text to be selected after this command is redone.
+	 */
+	public void setRedoSelectionLength(int selectionLength) {
+		fRedoSelectionLength = selectionLength;
+	}
+
+	/**
+	 * Sets the cursor position to be used after this command is undone.
+	 */
+	public void setUndoCursorPosition(int cursorPosition) {
+		fUndoCursorPosition = cursorPosition;
+	}
+
+	/**
+	 * Sets the length of text to be selected after this command is undone.
+	 */
+	public void setUndoSelectionLength(int selectionLength) {
+		fUndoSelectionLength = selectionLength;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/StructuredTextUndoManager.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/StructuredTextUndoManager.java
new file mode 100644
index 0000000..93a9b91
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/StructuredTextUndoManager.java
@@ -0,0 +1,650 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     Jesper Steen Møller - initial IDocumentExtension4 support - #102822
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.undo;
+
+import java.util.EventObject;
+
+import org.eclipse.emf.common.command.BasicCommandStack;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CommandStack;
+import org.eclipse.emf.common.command.CommandStackListener;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.jface.text.DocumentRewriteSession;
+import org.eclipse.jface.text.DocumentRewriteSessionType;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.SSECoreMessages;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.sse.core.internal.provisional.events.IStructuredDocumentListener;
+import org.eclipse.wst.sse.core.internal.provisional.events.NewDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.NoChangeEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.RegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
+import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentRegionsReplacedEvent;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.util.Assert;
+import org.eclipse.wst.sse.core.internal.util.Utilities;
+
+public class StructuredTextUndoManager implements IStructuredTextUndoManager {
+
+	class InternalCommandStackListener implements CommandStackListener {
+		public void commandStackChanged(EventObject event) {
+			resetInternalCommands();
+		}
+	}
+
+	class InternalStructuredDocumentListener implements IStructuredDocumentListener {
+
+		public void newModel(NewDocumentEvent structuredDocumentEvent) {
+			// Do nothing. Do not push the new model's structuredDocument
+			// changes
+			// onto the undo command stack, or else the user may be able to
+			// undo
+			// an existing file to an empty file.
+		}
+
+		public void noChange(NoChangeEvent structuredDocumentEvent) {
+			// Since "no change", do nothing.
+		}
+
+		public void nodesReplaced(StructuredDocumentRegionsReplacedEvent structuredDocumentEvent) {
+			processStructuredDocumentEvent(structuredDocumentEvent);
+		}
+
+		private void processStructuredDocumentEvent(String textDeleted, String textInserted, int textStart, int textEnd) {
+			if (fTextCommand != null && textStart == fTextCommand.getTextEnd()) {
+				// append to the text command
+				fTextCommand.setTextDeleted(fTextCommand.getTextDeleted().concat(textDeleted));
+				fTextCommand.setTextInserted(fTextCommand.getTextInserted().concat(textInserted));
+				fTextCommand.setTextEnd(textEnd);
+			}
+			else if (fTextCommand != null && textStart == fTextCommand.getTextStart() - 1 && textEnd <= fTextCommand.getTextEnd() - 1 && textDeleted.length() == 1 && textInserted.length() == 0 && fTextCommand.getTextDeleted().length() > 0) {
+				// backspace pressed
+				// erase a character in the file
+				fTextCommand.setTextDeleted(textDeleted.concat(fTextCommand.getTextDeleted()));
+				fTextCommand.setTextStart(textStart);
+			}
+			else {
+				createNewTextCommand(textDeleted, textInserted, textStart, textEnd);
+			}
+
+			// save cursor position
+			fCursorPosition = textEnd;
+		}
+
+		private void processStructuredDocumentEvent(StructuredDocumentEvent structuredDocumentEvent) {
+			// Note: fListening tells us if we should listen to the
+			// StructuredDocumentEvent.
+			// fListening is set to false right before the undo/redo process
+			// and
+			// then set to true again
+			// right after the undo/redo process to block out and ignore all
+			// StructuredDocumentEvents generated
+			// by the undo/redo process.
+
+			// Process StructuredDocumentEvent if fListening is true.
+			//
+			// We are executing a command from the command stack if the
+			// requester
+			// is a command (for example, undo/redo).
+			// We should not process the flat model event when we are
+			// executing a
+			// command from the command stack.
+			if (fUndoManagementEnabled && !(structuredDocumentEvent.getOriginalRequester() instanceof Command)) {
+				// check requester if not recording
+				if (!fRecording)
+					checkRequester(structuredDocumentEvent.getOriginalRequester());
+
+				// process the structuredDocumentEvent
+				String textDeleted = structuredDocumentEvent.getDeletedText();
+				String textInserted = structuredDocumentEvent.getText();
+				int textStart = structuredDocumentEvent.getOffset();
+				int textEnd = textStart + textInserted.length();
+				processStructuredDocumentEvent(textDeleted, textInserted, textStart, textEnd);
+			}
+		}
+
+		public void regionChanged(RegionChangedEvent structuredDocumentEvent) {
+			processStructuredDocumentEvent(structuredDocumentEvent);
+		}
+
+		public void regionsReplaced(RegionsReplacedEvent structuredDocumentEvent) {
+			processStructuredDocumentEvent(structuredDocumentEvent);
+		}
+
+	}
+
+	private static final String TEXT_CHANGE_TEXT = SSECoreMessages.Text_Change_UI_; //$NON-NLS-1$
+	private CommandStack fCommandStack = null;
+	private StructuredTextCompoundCommandImpl fCompoundCommand = null;
+	private String fCompoundCommandDescription = null;
+	private String fCompoundCommandLabel = null;
+	int fCursorPosition = 0;
+	// private IStructuredModel fStructuredModel = null;
+	private IDocument fDocument;
+	private InternalCommandStackListener fInternalCommandStackListener;
+	// private Map fTextViewerToListenerMap = new HashMap();
+	private IStructuredDocumentListener fInternalStructuredDocumentListener;
+	private IDocumentSelectionMediator[] fMediators = null;
+	private boolean fRecording = false;
+	private int fRecordingCount = 0;
+	private Object fRequester;
+	StructuredTextCommandImpl fTextCommand = null;
+	private int fUndoCursorPosition = -1;
+	boolean fUndoManagementEnabled = true;
+	private int fUndoSelectionLength = 0;
+
+	public StructuredTextUndoManager() {
+		this(new BasicCommandStack());
+	}
+
+	public StructuredTextUndoManager(CommandStack commandStack) {
+		setCommandStack(commandStack);
+	}
+
+	private void addDocumentSelectionMediator(IDocumentSelectionMediator mediator) {
+		if (!Utilities.contains(fMediators, mediator)) {
+			int oldSize = 0;
+
+			if (fMediators != null) {
+				// normally won't be null, but we need to be sure, for first
+				// time through
+				oldSize = fMediators.length;
+			}
+
+			int newSize = oldSize + 1;
+			IDocumentSelectionMediator[] newMediators = new IDocumentSelectionMediator[newSize];
+			if (fMediators != null) {
+				System.arraycopy(fMediators, 0, newMediators, 0, oldSize);
+			}
+
+			// add the new undo mediator to last position
+			newMediators[newSize - 1] = mediator;
+
+			// now switch new for old
+			fMediators = newMediators;
+		}
+		else {
+			removeDocumentSelectionMediator(mediator);
+			addDocumentSelectionMediator(mediator);
+		}
+	}
+
+	public void beginRecording(Object requester) {
+		beginRecording(requester, null, null);
+	}
+
+	public void beginRecording(Object requester, int cursorPosition, int selectionLength) {
+		beginRecording(requester, null, null);
+
+		fUndoCursorPosition = cursorPosition;
+		fUndoSelectionLength = selectionLength;
+	}
+
+	public void beginRecording(Object requester, String label) {
+		beginRecording(requester, label, null);
+	}
+
+	public void beginRecording(Object requester, String label, int cursorPosition, int selectionLength) {
+		beginRecording(requester, label, null);
+
+		fUndoCursorPosition = cursorPosition;
+		fUndoSelectionLength = selectionLength;
+	}
+
+	public void beginRecording(Object requester, String label, String description) {
+		// save the requester
+		fRequester = requester;
+
+		// update label and desc only on the first level when recording is
+		// nested
+		if (fRecordingCount == 0) {
+			fCompoundCommandLabel = label;
+			if (fCompoundCommandLabel == null)
+				fCompoundCommandLabel = TEXT_CHANGE_TEXT;
+
+			fCompoundCommandDescription = description;
+			if (fCompoundCommandDescription == null)
+				fCompoundCommandDescription = TEXT_CHANGE_TEXT;
+
+			// clear commands
+			fTextCommand = null;
+			fCompoundCommand = null;
+		}
+
+		// update counter and flag
+		fRecordingCount++;
+		fRecording = true;
+
+		// no undo cursor position and undo selection length specified
+		// reset undo cursor position and undo selection length
+		fUndoCursorPosition = -1;
+		fUndoSelectionLength = 0;
+	}
+
+	public void beginRecording(Object requester, String label, String description, int cursorPosition, int selectionLength) {
+		beginRecording(requester, label, description);
+
+		fUndoCursorPosition = cursorPosition;
+		fUndoSelectionLength = selectionLength;
+	}
+
+	void checkRequester(Object requester) {
+		if (fRequester != null && !fRequester.equals(requester)) {
+			// Force restart of recording so the last compound command is
+			// closed.
+			//
+			// However, we should not force restart of recording when the
+			// request came from StructuredDocumentToTextAdapter or
+			// XMLModelImpl
+			// because cut/paste requests and character inserts to the
+			// textViewer are from StructuredDocumentToTextAdapter,
+			// and requests to delete a node in the XMLTableTreeViewer are
+			// from XMLModelImpl (which implements IStructuredModel).
+
+			if (!(requester instanceof IStructuredModel || requester instanceof IStructuredDocument)) {
+				resetInternalCommands();
+			}
+		}
+	}
+
+
+
+	public void connect(IDocumentSelectionMediator mediator) {
+		Assert.isNotNull(mediator);
+		if (fDocument == null) {
+			// add this undo manager as structured document listener
+			fDocument = mediator.getDocument();
+			// future_TODO: eventually we want to refactor or allow either
+			// type of document, but for now, we'll do instanceof check, and
+			// fail
+			// if not right type
+			if (fDocument instanceof IStructuredDocument) {
+				((IStructuredDocument) fDocument).addDocumentChangedListener(getInternalStructuredDocumentListener());
+			}
+			else {
+				throw new IllegalArgumentException("only meditator with structured documents currently handled"); //$NON-NLS-1$
+			}
+		}
+		else {
+			// if we've already had our document set, we'll just do this fail
+			// fast integrity check
+			if (!fDocument.equals(mediator.getDocument()))
+				throw new IllegalStateException("Connection to undo manager failed. Document for document selection mediator inconistent with undo manager."); //$NON-NLS-1$
+		}
+
+		addDocumentSelectionMediator(mediator);
+	}
+
+	void createNewTextCommand(String textDeleted, String textInserted, int textStart, int textEnd) {
+		StructuredTextCommandImpl textCommand = new StructuredTextCommandImpl(fDocument);
+		textCommand.setLabel(TEXT_CHANGE_TEXT);
+		textCommand.setDescription(TEXT_CHANGE_TEXT);
+		textCommand.setTextStart(textStart);
+		textCommand.setTextEnd(textEnd);
+		textCommand.setTextDeleted(textDeleted);
+		textCommand.setTextInserted(textInserted);
+
+		if (fRecording) {
+			if (fCompoundCommand == null) {
+				StructuredTextCompoundCommandImpl compoundCommand = new StructuredTextCompoundCommandImpl();
+				compoundCommand.setUndoCursorPosition(fUndoCursorPosition);
+				compoundCommand.setUndoSelectionLength(fUndoSelectionLength);
+
+				compoundCommand.setLabel(fCompoundCommandLabel);
+				compoundCommand.setDescription(fCompoundCommandDescription);
+				compoundCommand.append(textCommand);
+
+				fCompoundCommand = compoundCommand;
+			}
+			else {
+				fCompoundCommand.append(textCommand);
+			}
+		}
+		else {
+			fCommandStack.execute(textCommand);
+		}
+
+		fTextCommand = textCommand;
+	}
+
+	/**
+	 * Disable undo management.
+	 */
+	public void disableUndoManagement() {
+		fUndoManagementEnabled = false;
+	}
+
+	public void disconnect(IDocumentSelectionMediator mediator) {
+		removeDocumentSelectionMediator(mediator);
+
+		if (fMediators != null && fMediators.length == 0 && fDocument != null) {
+			// remove this undo manager as structured document listener
+			// future_TODO: eventually we want to refactor or allow either
+			// type of document, but for now, we'll do instanceof check, and
+			// fail
+			// if not right type
+			if (fDocument instanceof IStructuredDocument) {
+				((IStructuredDocument) fDocument).removeDocumentChangedListener(getInternalStructuredDocumentListener());
+			}
+			else {
+				throw new IllegalArgumentException("only meditator with structured documents currently handled"); //$NON-NLS-1$
+			}
+			// if no longer listening to document, then dont even track it
+			// anymore
+			// (this allows connect to reconnect to document again)
+			fDocument = null;
+		}
+	}
+
+	public void enableUndoManagement() {
+		fUndoManagementEnabled = true;
+	}
+
+	public void endRecording(Object requester) {
+		int cursorPosition = (fTextCommand != null) ? fTextCommand.getTextEnd() : -1;
+		int selectionLength = 0;
+
+		endRecording(requester, cursorPosition, selectionLength);
+	}
+
+	public void endRecording(Object requester, int cursorPosition, int selectionLength) {
+		// Recording could be stopped by forceEndOfPendingCommand(). Make sure
+		// we are still recording before proceeding, or else fRecordingCount
+		// may not be balanced.
+		if (fRecording) {
+			if (fCompoundCommand != null) {
+				fCompoundCommand.setRedoCursorPosition(cursorPosition);
+				fCompoundCommand.setRedoSelectionLength(selectionLength);
+			}
+
+			// end recording is a logical stopping point for text command,
+			// even when fRecordingCount > 0 (in nested beginRecording)
+			fTextCommand = null;
+
+			// update counter and flag
+			if (fRecordingCount > 0)
+				fRecordingCount--;
+			if (fRecordingCount == 0) {
+				
+				// Finally execute the commands accumulated in the compound command.
+				
+				if (fCompoundCommand != null) {
+					fCommandStack.execute(fCompoundCommand);
+				}
+				
+				fRecording = false;
+
+				// reset compound command only when fRecordingCount ==
+				// 0
+				fCompoundCommand = null;
+				fCompoundCommandLabel = null;
+				fCompoundCommandDescription = null;
+
+				// Also reset fRequester
+				fRequester = null;
+			}
+		}
+	}
+
+	/**
+	 * Utility method to find model given document
+	 */
+	private IStructuredModel findStructuredModel(IDocument document) {
+		IModelManager modelManager = StructuredModelManager.getModelManager();
+		IStructuredModel structuredModel = modelManager.getExistingModelForRead(document);
+		return structuredModel;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.undo.IStructuredTextUndoManager#forceEndOfPendingCommand(java.lang.Object,
+	 *      int, int)
+	 */
+	public void forceEndOfPendingCommand(Object requester, int currentPosition, int length) {
+		if (fRecording)
+			endRecording(requester, currentPosition, length);
+		else
+			resetInternalCommands();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.wst.sse.core.undo.IStructuredTextUndoManager#getCommandStack()
+	 */
+	public CommandStack getCommandStack() {
+		return fCommandStack;
+	}
+
+	/**
+	 * @return
+	 */
+	private CommandStackListener getInternalCommandStackListener() {
+		if (fInternalCommandStackListener == null) {
+			fInternalCommandStackListener = new InternalCommandStackListener();
+		}
+		return fInternalCommandStackListener;
+	}
+
+	/**
+	 * @return
+	 */
+	private IStructuredDocumentListener getInternalStructuredDocumentListener() {
+		if (fInternalStructuredDocumentListener == null) {
+			fInternalStructuredDocumentListener = new InternalStructuredDocumentListener();
+		}
+		return fInternalStructuredDocumentListener;
+	}
+
+	public Command getRedoCommand() {
+		return fCommandStack.getRedoCommand();
+	}
+
+	public Command getUndoCommand() {
+		return fCommandStack.getUndoCommand();
+	}
+
+	public void redo() {
+		redo(null);
+	}
+
+	public void redo(IDocumentSelectionMediator requester) {
+		IStructuredModel model = findStructuredModel(fDocument);
+
+		if (redoable()) {
+			IDocumentExtension4 docExt4 = null;
+			DocumentRewriteSession rewriteSession = null;
+			try {
+				if (model != null)
+					model.aboutToChangeModel();
+
+				Command redoCommand = getRedoCommand();
+				if (redoCommand instanceof CompoundCommand &&
+						model.getStructuredDocument() instanceof IDocumentExtension4) {
+					docExt4 = (IDocumentExtension4)model.getStructuredDocument();
+				}
+				rewriteSession = (docExt4 == null) ? null :
+					docExt4.startRewriteSession(DocumentRewriteSessionType.UNRESTRICTED);
+
+				// make sure to redo before setting document selection
+				fCommandStack.redo();
+
+				// set document selection
+				setRedoDocumentSelection(requester, redoCommand);
+			}
+			finally {
+				if (docExt4 != null && rewriteSession != null)
+					docExt4.stopRewriteSession(rewriteSession);
+				if (model != null) {
+					model.changedModel();
+					model.releaseFromRead();
+				}
+			}
+		}
+	}
+
+	public boolean redoable() {
+		return fCommandStack.canRedo();
+	}
+
+	private void removeDocumentSelectionMediator(IDocumentSelectionMediator mediator) {
+		if (fMediators != null && mediator != null) {
+			// if its not in the array, we'll ignore the request
+			if (Utilities.contains(fMediators, mediator)) {
+				int oldSize = fMediators.length;
+				int newSize = oldSize - 1;
+				IDocumentSelectionMediator[] newMediators = new IDocumentSelectionMediator[newSize];
+				int index = 0;
+				for (int i = 0; i < oldSize; i++) {
+					if (fMediators[i] == mediator) { // ignore
+					}
+					else {
+						// copy old to new if its not the one we are removing
+						newMediators[index++] = fMediators[i];
+					}
+				}
+				// now that we have a new array, let's switch it for the old
+				// one
+				fMediators = newMediators;
+			}
+		}
+	}
+
+	void resetInternalCommands() {
+		// Either the requester of the structured document change event is
+		// changed, or the command stack is changed. Need to reset internal
+		// commands so we won't continue to append changes.
+		fCompoundCommand = null;
+		fTextCommand = null;
+
+		// Also reset fRequester
+		fRequester = null;
+	}
+
+	public void setCommandStack(CommandStack commandStack) {
+		if (fCommandStack != null)
+			fCommandStack.removeCommandStackListener(getInternalCommandStackListener());
+
+		fCommandStack = commandStack;
+
+		if (fCommandStack != null)
+			fCommandStack.addCommandStackListener(getInternalCommandStackListener());
+	}
+
+	private void setRedoDocumentSelection(IDocumentSelectionMediator requester, Command command) {
+		int cursorPosition = -1;
+		int selectionLength = 0;
+
+		if (command instanceof CommandCursorPosition) {
+			CommandCursorPosition commandCursorPosition = (CommandCursorPosition) command;
+			cursorPosition = commandCursorPosition.getRedoCursorPosition();
+			selectionLength = commandCursorPosition.getRedoSelectionLength();
+		}
+		else if (command instanceof StructuredTextCommand) {
+			StructuredTextCommand structuredTextCommand = (StructuredTextCommand) command;
+			cursorPosition = structuredTextCommand.getTextStart();
+			selectionLength = structuredTextCommand.getTextInserted().length();
+		}
+
+		if (cursorPosition > -1 && fMediators != null && fMediators.length > 0) {
+			for (int i = 0; i < fMediators.length; i++) {
+				IDocument document = fMediators[i].getDocument();
+				fMediators[i].undoOperationSelectionChanged(new UndoDocumentEvent(requester, document, cursorPosition, selectionLength));
+			}
+		}
+	}
+
+	private void setUndoDocumentSelection(IDocumentSelectionMediator requester, Command command) {
+		int cursorPosition = -1;
+		int selectionLength = 0;
+
+		if (command instanceof CommandCursorPosition) {
+			CommandCursorPosition commandCursorPosition = (CommandCursorPosition) command;
+			cursorPosition = commandCursorPosition.getUndoCursorPosition();
+			selectionLength = commandCursorPosition.getUndoSelectionLength();
+		}
+		else if (command instanceof StructuredTextCommand) {
+			StructuredTextCommand structuredTextCommand = (StructuredTextCommand) command;
+			cursorPosition = structuredTextCommand.getTextStart();
+			selectionLength = structuredTextCommand.getTextDeleted().length();
+		}
+
+		if (cursorPosition > -1 && fMediators != null && fMediators.length > 0) {
+			for (int i = 0; i < fMediators.length; i++) {
+				IDocument document = fMediators[i].getDocument();
+				fMediators[i].undoOperationSelectionChanged(new UndoDocumentEvent(requester, document, cursorPosition, selectionLength));
+			}
+		}
+	}
+
+	public void undo() {
+		undo(null);
+	}
+
+	public void undo(IDocumentSelectionMediator requester) {
+		// Force an endRecording before undo.
+		//
+		// For example, recording was turned on on the Design Page of
+		// PageDesigner.
+		// Then undo is invoked on the Source Page. Recording should be
+		// stopped before we undo.
+		// Note that redo should not be available when we switch to the Source
+		// Page.
+		// Therefore, this force ending of recording is not needed in redo.
+		if (fRecording)
+			endRecording(this);
+
+		if (undoable()) {
+			IStructuredModel model = findStructuredModel(fDocument);
+			IDocumentExtension4 docExt4 = null;
+			DocumentRewriteSession rewriteSession = null;
+
+			try {
+				if (model != null)
+					model.aboutToChangeModel();
+
+				Command undoCommand = getUndoCommand();
+				if (undoCommand instanceof CompoundCommand &&
+						model.getStructuredDocument() instanceof IDocumentExtension4) {
+					docExt4 = (IDocumentExtension4)model.getStructuredDocument();
+				}
+				rewriteSession = (docExt4 == null) ? null :
+					docExt4.startRewriteSession(DocumentRewriteSessionType.UNRESTRICTED);
+				
+				// make sure to undo before setting document selection
+				fCommandStack.undo();
+
+				// set document selection
+				setUndoDocumentSelection(requester, undoCommand);
+			}
+			finally {
+				if (docExt4 != null && rewriteSession != null)
+					docExt4.stopRewriteSession(rewriteSession);
+				if (model != null) {
+					model.changedModel();
+					model.releaseFromRead();
+				}
+			}
+		}
+	}
+
+	public boolean undoable() {
+		return fCommandStack.canUndo();
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/UndoDocumentEvent.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/UndoDocumentEvent.java
new file mode 100644
index 0000000..0fee467
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/undo/UndoDocumentEvent.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.undo;
+
+import org.eclipse.jface.text.IDocument;
+
+public class UndoDocumentEvent {
+	private IDocument fDocument;
+	private int fLength;
+	private int fOffset;
+	private IDocumentSelectionMediator fRequester;
+
+	public UndoDocumentEvent(IDocumentSelectionMediator requester, IDocument document, int offset, int length) {
+		fRequester = requester;
+		fDocument = document;
+		fOffset = offset;
+		fLength = length;
+	}
+
+	public IDocument getDocument() {
+		return fDocument;
+	}
+
+	public int getLength() {
+		return fLength;
+	}
+
+	public int getOffset() {
+		return fOffset;
+	}
+
+	public IDocumentSelectionMediator getRequester() {
+		return fRequester;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/AbstractMemoryListener.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/AbstractMemoryListener.java
new file mode 100644
index 0000000..46c60a8
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/AbstractMemoryListener.java
@@ -0,0 +1,205 @@
+/*******************************************************************************

+ * Copyright (c) 2009 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.wst.sse.core.internal.util;

+

+import java.util.ArrayList;

+import java.util.Arrays;

+import java.util.Hashtable;

+import java.util.List;

+

+import org.eclipse.core.runtime.Assert;

+import org.eclipse.core.runtime.Platform;

+import org.eclipse.wst.sse.core.internal.Logger;

+import org.eclipse.wst.sse.core.internal.SSECorePlugin;

+import org.osgi.framework.Bundle;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.BundleException;

+import org.osgi.framework.ServiceRegistration;

+import org.osgi.service.event.Event;

+import org.osgi.service.event.EventAdmin;

+import org.osgi.service.event.EventConstants;

+import org.osgi.service.event.EventHandler;

+

+/**

+ * This responds to memory events.

+ * 

+ * Create an instance of a child of this class with the events you are interested in.

+ * Then call connect() to start listening. To stop listening call disconnect();

+ */

+public abstract class AbstractMemoryListener implements EventHandler {

+	/**

+	 * The event that indicates that memory is running low at the lowest severity.

+	 * Listeners are requested to release caches that can easily be recomputed.

+	 * The Java VM is not seriously in trouble, but process size is getting higher than 

+	 * is deemed acceptable.

+	 */

+	public static final String SEV_NORMAL = "org/eclipse/equinox/events/MemoryEvent/NORMAL"; //$NON-NLS-1$

+	

+	/**

+	 * The event that indicates that memory is running low at medium severity. 

+	 * Listeners are requested to release intermediate build results, complex models, etc.

+	 * Memory is getting low and may cause operating system level stress, such as swapping.

+	 */

+	public static final String SEV_SERIOUS = "org/eclipse/equinox/events/MemoryEvent/SERIOUS"; //$NON-NLS-1$

+	

+	/**

+	 * The event that indicates that memory is running low at highest severity.

+	 * Listeners are requested to do things like close editors and perspectives, close database connections, etc.

+	 * Restoring these resources and caches constitutes lots of work, but memory is so low that

+	 * drastic measures are required.

+	 */

+	public static final String SEV_CRITICAL = "org/eclipse/equinox/events/MemoryEvent/CRITICAL"; //$NON-NLS-1$

+	

+	/**

+	 * All of the valid memory severities

+	 */

+	public static final String[] SEV_ALL = { SEV_NORMAL, SEV_SERIOUS, SEV_CRITICAL };

+

+	/**

+	 * Used to register the {@link EventAdmin} listener

+	 */

+	private static BundleContext CONTEXT =

+		(SSECorePlugin.getDefault() != null) ?

+				SSECorePlugin.getDefault().getBundle().getBundleContext() : null;

+

+	/**

+	 * the severities that will be reacted to

+	 */

+	private final List fSeverities;

+	

+	/**

+	 * service used to register this listener

+	 */

+	private ServiceRegistration fRegisterService;

+

+	/**

+	 * Will listen to all memory events

+	 */

+	public AbstractMemoryListener() {

+		this(AbstractMemoryListener.SEV_ALL);

+	}

+

+	/**

+	 * Will listen to memory events of the given <code>severity</code>

+	 * 

+	 * @param severity listen for memory events of this severity

+	 */

+	public AbstractMemoryListener(String severity) {

+		Assert.isNotNull(severity, "Severity can not be null"); //$NON-NLS-1$

+		

+		List severities = new ArrayList(1);

+		severities.add(severity);

+		fSeverities = severities;

+	}

+	

+	/**

+	 * Will listen to memory events of the given <code>severities</code>

+	 * 

+	 * @param severities listen for memory events for any of these severities

+	 */

+	public AbstractMemoryListener(String[] severities) {

+		Assert.isNotNull(severities, "Severities can not be null"); //$NON-NLS-1$

+		Assert.isLegal(severities.length > 0, "Severities must specify at least one severity"); //$NON-NLS-1$

+		

+		fSeverities = Arrays.asList(severities);

+	}

+

+	/**

+	 * Will listen to memory events of the given <code>severities</code>

+	 * 

+	 * @param severities listen for memory events for any of these severities

+	 */

+	public AbstractMemoryListener(List severities) {

+		Assert.isNotNull(severities, "Severities can not be null"); //$NON-NLS-1$

+		Assert.isLegal(!severities.isEmpty(), "Severities must specify at least one severity"); //$NON-NLS-1$

+		fSeverities = severities;

+	}

+

+	/**

+	 * Connect this listener to the {@link EventAdmin}

+	 */

+	public final void connect() {

+		if (CONTEXT != null) {

+			// NOTE: This is TEMPORARY CODE needed to load the plugin

+			// until its done automatically by the product

+			// TODO: Remove me

+			Bundle b = Platform.getBundle("org.eclipse.equinox.event"); //$NON-NLS-1$

+			if (b != null && b.getState() == Bundle.RESOLVED) {

+				try {

+					b.start(Bundle.START_TRANSIENT);

+				}

+				catch (BundleException e) {

+					e.printStackTrace();

+				}

+			}

+			// end remove me

+			

+			//register this handler

+			String[] severities = (String[])fSeverities.toArray(new String[fSeverities.size()]);

+			Hashtable prop = new Hashtable(1);

+			prop.put(EventConstants.EVENT_TOPIC, severities);

+			fRegisterService = CONTEXT.registerService(EventHandler.class.getName(), this, prop);

+			

+			//call any implementer specific connect code

+			doConnect();

+		} else {

+			Logger.log(Logger.WARNING, "Error accessing bundle context. Is Platform running? Not tracking memory events. "); //$NON-NLS-1$

+		}

+	}

+

+	/**

+	 * Disconnect this listener to the {@link EventAdmin}

+	 */

+	public final void disconnect() {

+		if (fRegisterService != null) {

+			fRegisterService.unregister();

+			fRegisterService = null;

+		}

+		

+		//call any implementer specific disconnect code

+		doDisconnect();

+	}

+

+	/**

+	 * <p>Filter out any events that are not of the type that this listener handles</p>

+	 * 

+	 * @see org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event)

+	 */

+	public final void handleEvent(Event event) {

+		if (fSeverities.contains(event.getTopic())) {

+			handleMemoryEvent(event);

+		}

+	}

+

+	/**

+	 * Implementing child classes may assume that only {@link Event}s of the types

+	 * given to the constructor will be given to this method.

+	 * 

+	 * @param event the {@link Event} with a topic equal to one of the memory

+	 * severities that this listener is listening for

+	 */

+	protected abstract void handleMemoryEvent(Event event);

+	

+	/**

+	 * Implementers may overrun this method to do setup after connection of this listener

+	 */

+	protected void doConnect() {

+		//do nothing by default

+	}

+	

+	/**

+	 * Implementers may overrun this method to do tear down after disconnection of this listener

+	 */

+	protected void doDisconnect() {

+		//do nothing by default

+	}

+}

diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Assert.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Assert.java
new file mode 100644
index 0000000..f3d1ee0
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Assert.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.util;
+
+
+/**
+ * <code>Assert</code> is useful for for embedding runtime sanity checks in
+ * code. The predicate methods all test a condition and throw some type of
+ * unchecked exception if the condition does not hold.
+ * <p>
+ * Assertion failure exceptions, like most runtime exceptions, are thrown when
+ * something is misbehaving. Assertion failures are invariably unspecified
+ * behavior; consequently, clients should never rely on these being thrown
+ * (and certainly should not being catching them specifically).
+ * </p>
+ */
+public final class Assert {
+
+	/**
+	 * <code>AssertionFailedException</code> is a runtime exception thrown
+	 * by some of the methods in <code>Assert</code>.
+	 * <p>
+	 * This class is not declared public to prevent some misuses; programs
+	 * that catch or otherwise depend on assertion failures are susceptible to
+	 * unexpected breakage when assertions in the code are added or removed.
+	 * </p>
+	 */
+	class AssertionFailedException extends RuntimeException {
+		/**
+		 * Comment for <code>serialVersionUID</code>
+		 */
+		private static final long serialVersionUID = 1L;
+
+		/**
+		 * Constructs a new exception.
+		 */
+		public AssertionFailedException() {
+			super();
+		}
+
+		/**
+		 * Constructs a new exception with the given message.
+		 */
+		public AssertionFailedException(String detail) {
+			super(detail);
+		}
+	}
+
+	/**
+	 * Asserts that an argument is legal. If the given boolean is not
+	 * <code>true</code>, an <code>IllegalArgumentException</code> is
+	 * thrown.
+	 * 
+	 * @param expression
+	 *            the outcode of the check
+	 * @return <code>true</code> if the check passes (does not return if the
+	 *         check fails)
+	 * @exception IllegalArgumentException
+	 *                if the legality test failed
+	 */
+	public static boolean isLegal(boolean expression) {
+		return isLegal(expression, ""); //$NON-NLS-1$
+	}
+
+	/**
+	 * Asserts that an argument is legal. If the given boolean is not
+	 * <code>true</code>, an <code>IllegalArgumentException</code> is
+	 * thrown. The given message is included in that exception, to aid
+	 * debugging.
+	 * 
+	 * @param expression
+	 *            the outcode of the check
+	 * @param message
+	 *            the message to include in the exception
+	 * @return <code>true</code> if the check passes (does not return if the
+	 *         check fails)
+	 * @exception IllegalArgumentException
+	 *                if the legality test failed
+	 */
+	public static boolean isLegal(boolean expression, String message) {
+		if (!expression)
+			throw new IllegalArgumentException();
+		return expression;
+	}
+
+	/**
+	 * Asserts that the given object is not <code>null</code>. If this is
+	 * not the case, some kind of unchecked exception is thrown.
+	 * 
+	 * @param object
+	 *            the value to test
+	 * @exception IllegalArgumentException
+	 *                if the object is <code>null</code>
+	 */
+	public static void isNotNull(Object object) {
+		isNotNull(object, ""); //$NON-NLS-1$
+	}
+
+	/**
+	 * Asserts that the given object is not <code>null</code>. If this is
+	 * not the case, some kind of unchecked exception is thrown. The given
+	 * message is included in that exception, to aid debugging.
+	 * 
+	 * @param object
+	 *            the value to test
+	 * @param message
+	 *            the message to include in the exception
+	 * @exception IllegalArgumentException
+	 *                if the object is <code>null</code>
+	 */
+	public static void isNotNull(Object object, String message) {
+		if (object == null) {
+			//Logger.log(Logger.ERROR, "null_argument: " + message); //$NON-NLS-1$
+			throw new Assert().new AssertionFailedException(message);
+		}
+	}
+
+	/**
+	 * Asserts that the given boolean is <code>true</code>. If this is not
+	 * the case, some kind of unchecked exception is thrown.
+	 * 
+	 * @param expression
+	 *            the outcode of the check
+	 * @return <code>true</code> if the check passes (does not return if the
+	 *         check fails)
+	 */
+	public static boolean isTrue(boolean expression) {
+		return isTrue(expression, ""); //$NON-NLS-1$
+	}
+
+	/**
+	 * Asserts that the given boolean is <code>true</code>. If this is not
+	 * the case, some kind of unchecked exception is thrown. The given message
+	 * is included in that exception, to aid debugging.
+	 * 
+	 * @param expression
+	 *            the outcode of the check
+	 * @param message
+	 *            the message to include in the exception
+	 * @return <code>true</code> if the check passes (does not return if the
+	 *         check fails)
+	 */
+	public static boolean isTrue(boolean expression, String message) {
+		if (!expression) {
+			throw new Assert().new AssertionFailedException(message);
+		}
+		return expression;
+	}
+
+	/* This class is not intended to be instantiated. */
+	private Assert() {
+		super();
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Debug.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Debug.java
new file mode 100644
index 0000000..3df8954
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Debug.java
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (Intalio) - bug 300430 - String concatenation
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.util;
+
+
+
+import java.util.Enumeration;
+
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionCollection;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer;
+import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
+
+
+public final class Debug {
+	public static final boolean checkForMemoryLeaks = false;
+
+	public static final boolean collectStats = false;
+
+	public static final int DEBUG = 0;
+
+	public static final boolean DEBUG_THREADLOCAL = false;
+
+	public static final boolean debugBreakpoints = false;
+	public static final boolean debugCaretMediator = false;
+	public static final boolean debugDisplayTreePositions = false;
+	//
+	public static final boolean debugMediator = false;
+	//
+	public static final boolean debugNotification = false;
+	public static final boolean debugNotificationAndEvents = false;
+
+	public static final boolean debugNotifyDeferred = false;
+	public static final boolean debugReconciling = false;
+	//
+	public static final boolean debugRtfFormatProvider = false;
+	//
+	public static final boolean debugStructuredDocument = false;
+	public static final boolean debugTaglibs = false;
+	//
+	public static final boolean debugTokenizer = false;
+	//
+	public static final boolean debugTreeModel = false;
+	public static final boolean debugUpdateTreePositions = false;
+	public static final boolean displayInfo = false;
+
+	/** effects output of Logger */
+	public static final boolean displayToConsole = true;
+	public static final boolean displayWarnings = false;
+	//
+	public static final boolean headParsing = false;
+	public static final boolean jsDebugContextAssist = false;
+	//
+	public static final boolean jsDebugSyntaxColoring = false;
+
+	public static final boolean LOCKS = false;
+	// 
+	public static final boolean perfTest = false;
+	public static final boolean perfTestAdapterClassLoading = false;
+	public static final boolean perfTestFormat = false;
+	public static final boolean perfTestRawStructuredDocumentOnly = false;
+	public static final boolean perfTestStructuredDocumentEventOnly = false;
+	public static final boolean perfTestStructuredDocumentOnly = false;
+
+	//
+	public static final boolean syntaxHighlighting = false;
+	//
+	public static final boolean useStandardEolInWidget = false;
+
+	/**
+	 * For tests and debug only
+	 */
+
+	public static final void dump(IStructuredDocument structuredDocument) {
+		dump(structuredDocument, false);
+	}
+
+	public static final void dump(IStructuredDocument structuredDocument, boolean verbose) {
+		ITextRegionCollection flatNode = null;
+		System.out.println("Dump of structuredDocument:"); //$NON-NLS-1$
+		IStructuredDocumentRegionList flatNodes = structuredDocument.getRegionList();
+		Enumeration structuredDocumentRegions = flatNodes.elements();
+		while (structuredDocumentRegions.hasMoreElements()) {
+			flatNode = (ITextRegionCollection) structuredDocumentRegions.nextElement();
+			if (!verbose) {
+				String outString = flatNode.toString();
+				outString = org.eclipse.wst.sse.core.utils.StringUtils.escape(outString);
+				System.out.println(outString);
+			} else {
+				dump(flatNode, verbose);
+			}
+		}
+		System.out.println();
+		System.out.println("= = = = = ="); //$NON-NLS-1$
+		System.out.println();
+	}
+
+	/**
+	 * @param flatNode
+	 * @param verbose
+	 */
+	public static final void dump(ITextRegionCollection region, boolean verbose) {
+		if (region == null)
+			return;
+		if (verbose) {
+			printParent(region);
+		}
+		printChildRegions(region, 0);
+	}
+
+	private static void printChildRegions(ITextRegionCollection region, int depth) {
+		if (region != null) {
+			// ==> // ITextRegionCollection regionCollection = region;
+			System.out.println(region);
+			ITextRegionList regionList = region.getRegions();
+			for (int i = 0; i < regionList.size(); i++) {
+				ITextRegion r = regionList.get(i);
+				if (r instanceof ITextRegionCollection) {
+					ITextRegionCollection rc = (ITextRegionCollection) r;
+					printChildRegions(rc, depth++);
+				} else {
+					System.out.println(space(depth) + r);
+					depth--;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Simple utility to make sure println's are some what in order
+	 */
+	public static final synchronized void println(String msg) {
+		System.out.println(System.currentTimeMillis() + "\t" + msg); //$NON-NLS-1$
+	}
+
+	private static void printParent(IStructuredDocumentRegion region) {
+		System.out.println("    [parent document: " + toStringUtil(region.getParentDocument()) + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	private static void printParent(ITextRegionCollection region) {
+		if (region instanceof IStructuredDocumentRegion) {
+			printParent((IStructuredDocumentRegion) region);
+		} else if (region instanceof ITextRegionContainer) {
+			printParent((ITextRegionContainer) region);
+		} else
+			System.out.println("    [parent document: " + "(na)" + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	}
+
+	private static void printParent(ITextRegionContainer region) {
+		System.out.println("    [parent document: " + toStringUtil(region.getParent()) + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+
+	/**
+	 * @param depth
+	 * @return
+	 */
+	private static String space(int depth) {
+		String result = "  "; //$NON-NLS-1$
+		StringBuffer sb = new StringBuffer(result);
+		for (int i = 0; i < depth; i++) {
+			sb.append("  "); //$NON-NLS-1$
+		}
+		result = sb.toString();
+		return result;
+	}
+
+	public static final String toStringUtil(IStructuredDocument object) {
+		String className = object.getClass().getName();
+		String shortClassName = className.substring(className.lastIndexOf(".") + 1); //$NON-NLS-1$
+		String result = shortClassName;
+		// NOTE: if the document held by any region has been updated and the
+		// region offsets have not
+		// yet been updated, the output from this method invalid.
+		return result;
+
+	}
+
+	public static final String toStringUtil(ITextRegionCollection object) {
+		String className = object.getClass().getName();
+		String shortClassName = className.substring(className.lastIndexOf(".") + 1); //$NON-NLS-1$
+		String result = shortClassName;
+		// NOTE: if the document held by any region has been updated and the
+		// region offsets have not
+		// yet been updated, the output from this method invalid.
+		return result;
+
+	}
+
+	/**
+	 * Debug constructor comment.
+	 */
+	public Debug() {
+		super();
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/DocumentInputStream.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/DocumentInputStream.java
new file mode 100644
index 0000000..fad0951
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/DocumentInputStream.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+
+public class DocumentInputStream extends InputStream {
+	private IDocument fDocument;
+	private int fMark = -1;
+	private int fPosition = 0;
+
+	public DocumentInputStream(IDocument source) {
+		super();
+		fDocument = source;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#available()
+	 */
+	public int available() throws IOException {
+		return fDocument.getLength() - fPosition;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#close()
+	 */
+	public void close() throws IOException {
+		this.fDocument = null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#mark(int)
+	 */
+	public synchronized void mark(int readlimit) {
+		fMark = fPosition;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#markSupported()
+	 */
+	public boolean markSupported() {
+		return true;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#read()
+	 */
+	public int read() throws IOException {
+		try {
+			if (fPosition < fDocument.getLength())
+				return fDocument.getChar(fPosition++);
+			else
+				return -1;
+		} catch (BadLocationException e) {
+			throw new IOException(e.getMessage());
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#reset()
+	 */
+	public synchronized void reset() throws IOException {
+		fPosition = fMark;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.io.InputStream#skip(long)
+	 */
+	public long skip(long n) throws IOException {
+		long skipped = n;
+		if (n < fDocument.getLength() - fPosition) {
+			skipped = n;
+			fPosition += skipped;
+		} else {
+			skipped = fDocument.getLength() - fPosition;
+			fPosition = fDocument.getLength();
+		}
+		return skipped;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/JarUtilities.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/JarUtilities.java
new file mode 100644
index 0000000..d2bedbb
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/JarUtilities.java
@@ -0,0 +1,394 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.sse.core.internal.Logger;
+
+
+public class JarUtilities {
+
+	/**
+	 * @see http://java.sun.com/products/jsp/errata_1_1_a_042800.html, Issues
+	 *      8 & 9
+	 * 
+	 *      "There are two cases. In both cases the TLD_URI is to be
+	 *      interpreted relative to the root of the Web Application. In the
+	 *      first case the TLD_URI refers to a TLD file directly. In the
+	 *      second case, the TLD_URI refers to a JAR file. If so, that JAR
+	 *      file should have a TLD at location META-INF/taglib.tld."
+	 */
+	public static final String JSP11_TAGLIB = "META-INF/taglib.tld"; //$NON-NLS-1$
+
+	public static void closeJarFile(ZipFile file) {
+		if (file == null)
+			return;
+		try {
+			file.close();
+		}
+		catch (IOException ioe) {
+			// no cleanup can be done
+		}
+	}
+
+	/**
+	 * Provides a stream to a local copy of the input or null if not possible
+	 */
+	protected static InputStream getCachedInputStream(String jarFilename, String entryName) {
+		File testFile = new File(jarFilename);
+		if (!testFile.exists())
+			return getInputStream(ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(jarFilename)), entryName);
+
+		InputStream cache = null;
+		ZipFile jarfile = null;
+		try {
+			jarfile = new ZipFile(jarFilename);
+		}
+		catch (IOException ioExc) {
+			closeJarFile(jarfile);
+		}
+
+		if (jarfile != null) {
+			try {
+				ZipEntry zentry = jarfile.getEntry(entryName);
+				if (zentry != null) {
+					InputStream entryInputStream = null;
+					try {
+						entryInputStream = jarfile.getInputStream(zentry);
+					}
+					catch (IOException ioExc) {
+						// no cleanup can be done
+					}
+
+					if (entryInputStream != null) {
+						int c;
+						ByteArrayOutputStream buffer = null;
+						if (zentry.getSize() > 0) {
+							buffer = new ByteArrayOutputStream((int) zentry.getSize());
+						}
+						else {
+							buffer = new ByteArrayOutputStream();
+						}
+						// array dim restriction?
+						byte bytes[] = new byte[2048];
+						try {
+							while ((c = entryInputStream.read(bytes)) >= 0) {
+								buffer.write(bytes, 0, c);
+							}
+							cache = new ByteArrayInputStream(buffer.toByteArray());
+							closeJarFile(jarfile);
+						}
+						catch (IOException ioe) {
+							// no cleanup can be done
+						}
+						finally {
+							try {
+								entryInputStream.close();
+							}
+							catch (IOException e) {
+								// no cleanup can be done
+							}
+						}
+					}
+				}
+			}
+			finally {
+				closeJarFile(jarfile);
+			}
+		}
+		return cache;
+	}
+
+	private static InputStream copyAndCloseStream(InputStream original) {
+		ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+		InputStream cachedCopy = null;
+
+		if (original != null) {
+			int c;
+			// array dim restriction?
+			byte bytes[] = new byte[2048];
+			try {
+				while ((c = original.read(bytes)) >= 0) {
+					buffer.write(bytes, 0, c);
+				}
+				cachedCopy = new ByteArrayInputStream(buffer.toByteArray());
+				closeStream(original);
+			}
+			catch (IOException ioe) {
+				// no cleanup can be done
+			}
+		}
+		return cachedCopy;
+	}
+
+	/**
+	 * @param jarResource
+	 *            the zip file
+	 * @return a string array containing the entry paths to every file in this
+	 *         zip resource, excluding directories
+	 */
+	public static String[] getEntryNames(IResource jarResource) {
+		if (jarResource == null || jarResource.getType() != IResource.FILE || !jarResource.isAccessible())
+			return new String[0];
+
+		try {
+			return getEntryNames(jarResource.getFullPath().toString(), new ZipInputStream(((IFile) jarResource).getContents()), true);
+		}
+		catch (CoreException e) {
+			// no cleanup can be done
+		}
+
+		IPath location = jarResource.getLocation();
+		if (location != null)
+			return getEntryNames(location.toString());
+		return new String[0];
+	}
+
+	/**
+	 * @param jarFilename
+	 *            the location of the zip file
+	 * @return a string array containing the entry paths to every file in the
+	 *         zip file at this location, excluding directories
+	 */
+	public static String[] getEntryNames(String jarFilename) {
+		return getEntryNames(jarFilename, true);
+	}
+
+	private static String[] getEntryNames(String filename, ZipInputStream jarInputStream, boolean excludeDirectories) {
+		List entryNames = new ArrayList();
+		try {
+			ZipEntry z = jarInputStream.getNextEntry();
+			while (z != null) {
+				if (!(z.isDirectory() && excludeDirectories))
+					entryNames.add(z.getName());
+				z = jarInputStream.getNextEntry();
+			}
+		}
+		catch (ZipException zExc) {
+			Logger.log(Logger.WARNING_DEBUG, "JarUtilities ZipException: (stream) " + filename, zExc); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		catch (IOException ioExc) {
+			// no cleanup can be done
+		}
+		finally {
+			closeStream(jarInputStream);
+		}
+		String[] names = (String[]) entryNames.toArray(new String[0]);
+		return names;
+	}
+
+	private static void closeStream(InputStream inputStream) {
+		try {
+			inputStream.close();
+		}
+		catch (IOException e) {
+			// no cleanup can be done
+		}
+	}
+
+	/**
+	 * @param jarFilename
+	 *            the location of the zip file
+	 * @param excludeDirectories
+	 *            whether to not include directories in the results
+	 * @return a string array containing the entry paths to every file in the
+	 *         zip file at this location, excluding directories if indicated
+	 */
+	public static String[] getEntryNames(String jarFilename, boolean excludeDirectories) {
+		ZipFile jarfile = null;
+		List entryNames = new ArrayList();
+		File f = new File(jarFilename);
+		if (f.exists() && f.canRead()) {
+			try {
+				jarfile = new ZipFile(f);
+				Enumeration entries = jarfile.entries();
+				while (entries.hasMoreElements()) {
+					ZipEntry z = (ZipEntry) entries.nextElement();
+					if (!(z.isDirectory() && excludeDirectories))
+						entryNames.add(z.getName());
+				}
+			}
+			catch (ZipException zExc) {
+				Logger.log(Logger.WARNING_DEBUG, "JarUtilities ZipException: " + jarFilename + " " + zExc.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
+			}
+			catch (IOException ioExc) {
+				// no cleanup can be done
+			}
+			finally {
+				closeJarFile(jarfile);
+			}
+		}
+		String[] names = (String[]) entryNames.toArray(new String[0]);
+		return names;
+	}
+
+	/**
+	 * @param jarResource
+	 *            the zip file
+	 * @param entryName
+	 *            the entry's path in the zip file
+	 * @return an InputStream to the contents of the given entry or null if
+	 *         not possible
+	 */
+	public static InputStream getInputStream(IResource jarResource, String entryName) {
+		if (jarResource == null || jarResource.getType() != IResource.FILE || !jarResource.isAccessible())
+			return null;
+
+		try {
+			InputStream zipStream = ((IFile) jarResource).getContents();
+			return getInputStream(jarResource.getFullPath().toString(), new ZipInputStream(zipStream), entryName);
+		}
+		catch (CoreException e) {
+			// no cleanup can be done, probably out of sync
+		}
+
+		IPath location = jarResource.getLocation();
+		if (location != null) {
+			return getInputStream(location.toString(), entryName);
+		}
+		return null;
+	}
+
+	private static InputStream getInputStream(String filename, ZipInputStream zip, String entryName) {
+		InputStream result = null;
+		try {
+			ZipEntry z = zip.getNextEntry();
+			while (z != null && !z.getName().equals(entryName)) {
+				z = zip.getNextEntry();
+			}
+			if (z != null) {
+				result = copyAndCloseStream(zip);
+			}
+		}
+		catch (ZipException zExc) {
+			Logger.log(Logger.WARNING_DEBUG, "JarUtilities ZipException: (stream) " + filename, zExc); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		catch (IOException ioExc) {
+			// no cleanup can be done
+		}
+		finally {
+			closeStream(zip);
+		}
+		return result;
+	}
+
+	/**
+	 * @param jarFilename
+	 *            the location of the zip file
+	 * @param entryName
+	 *            the entry's path in the zip file
+	 * @return an InputStream to the contents of the given entry or null if
+	 *         not possible
+	 */
+	public static InputStream getInputStream(String jarFilename, String entryName) {
+		// check sanity
+		if (jarFilename == null || jarFilename.length() < 1 || entryName == null || entryName.length() < 1)
+			return null;
+
+		// JAR files are not allowed to have leading '/' in member names
+		String internalName = null;
+		if (entryName.startsWith("/")) //$NON-NLS-1$
+			internalName = entryName.substring(1);
+		else
+			internalName = entryName;
+
+		return getCachedInputStream(jarFilename, internalName);
+	}
+
+	/**
+	 * @param url
+	 *            a URL pointint to a zip file
+	 * @return a cached copy of the contents at this URL, opening it as a file
+	 *         if it is a jar:file: URL, and using a URLConnection otherwise,
+	 *         or null if it could not be read. All sockets and file handles
+	 *         are closed as quickly as possible.
+	 */
+	public static InputStream getInputStream(URL url) {
+		String urlString = url.toString();
+		if (urlString.length() > 12 && urlString.startsWith("jar:file:") && urlString.indexOf("!/") > 9) { //$NON-NLS-1$ //$NON-NLS-2$
+			int fileIndex = urlString.indexOf("!/"); //$NON-NLS-1$ 
+			String jarFileName = urlString.substring(9, fileIndex);
+			if (fileIndex < urlString.length()) {
+				String jarPath = urlString.substring(fileIndex + 1);
+				return getInputStream(jarFileName, jarPath);
+			}
+		}
+
+		InputStream input = null;
+		JarURLConnection jarUrlConnection = null;
+		try {
+			URLConnection openConnection = url.openConnection();
+			openConnection.setDefaultUseCaches(false);
+			openConnection.setUseCaches(false);
+			if (openConnection instanceof JarURLConnection) {
+				jarUrlConnection = (JarURLConnection) openConnection;
+				JarFile jarFile = jarUrlConnection.getJarFile();
+				input = jarFile.getInputStream(jarUrlConnection.getJarEntry());
+			}
+			else {
+				input = openConnection.getInputStream();
+			}
+			if (input != null) {
+				return copyAndCloseStream(input);
+			}
+		}
+		catch (FileNotFoundException e) {
+			// May be a file URL connection, do not log
+		}
+		catch (IOException e) {
+			Logger.logException(e);
+		}
+		finally {
+			if (jarUrlConnection != null) {
+				try {
+					jarUrlConnection.getJarFile().close();
+				}
+				catch (IOException e) {
+					// ignore
+				}
+				catch (IllegalStateException e) {
+					/*
+					 * ignore. Can happen in case the stream.close() did close
+					 * the jar file see
+					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=140750
+					 */
+				}
+
+			}
+		}
+		return null;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/PathHelper.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/PathHelper.java
new file mode 100644
index 0000000..b835085
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/PathHelper.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (Intalio) - bug 300430 - String concatenation
+ *          
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.util;
+
+
+
+import java.io.File;
+import com.ibm.icu.util.StringTokenizer;
+
+/**
+ * Collection of helper methods to manage and convert links Originally part of
+ * the LinksManager 
+ */
+public class PathHelper {
+	public static final String BACKWARD_SLASH = "\\";//$NON-NLS-1$
+
+	public static final String FORWARD_SLASH = "/";//$NON-NLS-1$
+	public static final String RELATIVE_PATH_SIG = "../";//$NON-NLS-1$
+
+	/**
+	 * adjust relative path isside the absolute path
+	 */
+	public static String adjustPath(String path) {
+		int i = 0;
+		while ((i = path.indexOf(RELATIVE_PATH_SIG)) > 0) {
+			// split the string into two
+			String part1 = path.substring(0, i - 1);
+			String part2 = path.substring(i + RELATIVE_PATH_SIG.length() - 1);
+			// strip one path seg from part1
+			int j = part1.lastIndexOf(FORWARD_SLASH);
+			if (j == -1) {
+				// can't resolve. passed path is like
+				// E:/eclipseproject/../../sample.css.
+				return "";//$NON-NLS-1$
+			}
+			part1 = part1.substring(0, j);
+			path = part1 + part2;
+		}
+		return path;
+	}
+
+	/**
+	 * Append trailing url slash if needed
+	 */
+	public static String appendTrailingURLSlash(String input) {
+		// check to see already a slash
+		if (!input.endsWith(FORWARD_SLASH)) {
+			input += FORWARD_SLASH;
+		}
+		return input;
+	}
+
+	/**
+	 * Convert to relative url based on base
+	 */
+	public static String convertToRelative(String input, String base) {
+		// tokenize the strings
+		StringTokenizer inputTokenizer = new StringTokenizer(input, FORWARD_SLASH);
+		StringTokenizer baseTokenizer = new StringTokenizer(base, FORWARD_SLASH);
+		String token1 = "", token2 = "";//$NON-NLS-2$//$NON-NLS-1$
+		//
+		// Go through until equls
+		while (true) {
+			if (!inputTokenizer.hasMoreTokens() || !baseTokenizer.hasMoreTokens())
+				break;
+			token1 = baseTokenizer.nextToken();
+			token2 = inputTokenizer.nextToken();
+			if (!token1.equals(token2))
+				break;
+		}
+		// now generate the backs
+		String output = "";//$NON-NLS-1$
+		StringBuffer sb = new StringBuffer(output);
+		while (baseTokenizer.hasMoreTokens()) {
+			baseTokenizer.nextToken();
+			sb.append("../"); //$NON-NLS-1$
+		}
+		sb.append(token2);
+		// generate the rest
+		while (inputTokenizer.hasMoreTokens()) {
+			sb.append(FORWARD_SLASH);
+			sb.append(inputTokenizer.nextToken());
+		}
+		output = sb.toString();
+		return output;
+	}
+
+	/**
+	 * Return the containing folder path. Will handle both url and file path
+	 */
+	public static String getContainingFolderPath(String path) {
+		String retValue = path;
+
+		int urlSlashIndex = path.lastIndexOf(FORWARD_SLASH);
+		int filePathSlashIndex = path.lastIndexOf(File.separator);
+		int index = filePathSlashIndex;
+		if (urlSlashIndex > filePathSlashIndex)
+			index = urlSlashIndex;
+		if (index >= 0)
+			retValue = path.substring(0, index);
+		return retValue;
+	}
+
+	/**
+	 * Remove leading path separator
+	 */
+	public static String removeLeadingPathSeparator(String path) {
+		if (path.startsWith(File.separator))
+			path = path.substring(File.separator.length());
+		return path;
+	}
+
+	/**
+	 * Remove leading path separator
+	 */
+	public static String removeLeadingSeparator(String path) {
+		if (path.startsWith(File.separator))
+			path = path.substring(File.separator.length());
+		else if (path.startsWith(FORWARD_SLASH) || path.startsWith(BACKWARD_SLASH))
+			path = path.substring(FORWARD_SLASH.length());
+		return path;
+	}
+
+	/**
+	 * Switch to file path slashes
+	 */
+	public static String switchToFilePathSlashes(String path) {
+		path = path.replace(FORWARD_SLASH.charAt(0), File.separatorChar);
+		path = path.replace(BACKWARD_SLASH.charAt(0), File.separatorChar);
+		return path;
+	}
+
+	/**
+	 * Switch to file path slashes
+	 */
+	public static String switchToForwardSlashes(String path) {
+		path = path.replace(File.separatorChar, FORWARD_SLASH.charAt(0));
+		path = path.replace(BACKWARD_SLASH.charAt(0), FORWARD_SLASH.charAt(0));
+		return path;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/ProjectResolver.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/ProjectResolver.java
new file mode 100644
index 0000000..0a21f95
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/ProjectResolver.java
@@ -0,0 +1,259 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2007 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.util;
+
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
+
+import com.ibm.icu.util.StringTokenizer;
+
+/**
+ * @deprecated The URIResolver interface is deprecated. Use the resolver from
+ *             org.eclipse.wst.common.uriresolver.
+ */
+public class ProjectResolver implements URIResolver {
+	private String fFileBaseLocation = null;
+	private IProject fProject = null;
+
+	/**
+	 * It is strongly recommended that clients use
+	 * project.getAdapter(URIResolver.class) to obtain a URIResolver aware of
+	 * the Project's special requirements. Note that a URIResolver may not be
+	 * returned at all so manually creating this object may still be required.
+	 */
+	public ProjectResolver(IProject project) {
+		super();
+		fProject = project;
+	}
+
+	public String getFileBaseLocation() {
+		return fFileBaseLocation;
+	}
+
+	public String getLocationByURI(String uri) {
+		return getLocationByURI(uri, getFileBaseLocation());
+	}
+
+	// defect 244817 end
+	/**
+	 * Resolve the (possibly relative) URI acording to RFC1808 using the
+	 * default file base location. Resolves resource references into absolute
+	 * resource locations without ensuring that the resource actually exists.
+	 * 
+	 * Note: currently resolveCrossProjectLinks is ignored in this
+	 * implementation.
+	 */
+	public String getLocationByURI(String uri, boolean resolveCrossProjectLinks) {
+		return getLocationByURI(uri, getFileBaseLocation(), resolveCrossProjectLinks);
+	}
+
+	public String getLocationByURI(String uri, String baseReference) {
+		if (uri == null)
+			return null;
+		/*
+		 * defect 244817 try { URL aURL = new URL(uri);
+		 */
+		/**
+		 * An actual URL was given, but only the "file:///" protocol is
+		 * supported. Resolve the URI by finding the file to which it points.
+		 */
+		/*
+		 * defect 244817 if (!aURL.getProtocol().equals("platform")) {
+		 * //$NON-NLS-1$ if (aURL.getProtocol().equals("file") &&
+		 * (aURL.getHost().equals("localhost") || aURL.getHost().length() ==
+		 * 0)) { //$NON-NLS-2$//$NON-NLS-1$ return aURL.getFile(); } return
+		 * uri; } } catch (MalformedURLException mfuExc) { }
+		 */
+		// defect 244817 start
+		if (isFileURL(uri)) {
+			try {
+				URL url = new URL(uri);
+				return getPath(url);
+			}
+			catch (MalformedURLException e) {
+			}
+		}
+		// defect 244817 end
+
+		// which of the serveral are we suppose to use here?
+		//
+
+		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=71223
+		// Workaround for problem in URIHelper; uris starting with '/' are
+		// returned as-is.
+		String location = null;
+		if (uri.startsWith("/")) { //$NON-NLS-1$
+			IProject p = getProject();
+			if (p != null && p.isAccessible()) {
+				IFile file = p.getFile(uri);
+				
+				if (file.getLocation() != null) {
+					location = file.getLocation().toString();
+				}
+				if (location == null && file.getLocationURI() != null) {
+					location = file.getLocationURI().toString();
+				}
+				if (location == null) {
+					location = file.getFullPath().toString();
+				}
+			}
+		}
+		if(location == null) {
+			location = URIHelper.normalize(uri, baseReference, getRootLocationString());
+		}
+		return location;
+	}
+
+	/**
+	 * Perform the getLocationByURI action using the baseReference as the
+	 * point of reference instead of the default for this resolver
+	 * 
+	 * Note: currently resolveCrossProjectLinks is ignored in this
+	 * implementation.
+	 */
+	public String getLocationByURI(String uri, String baseReference, boolean resolveCrossProjectLinks) {
+		return getLocationByURI(uri, baseReference);
+	}
+
+	/**
+	 * 
+	 * @param path
+	 * @param host
+	 * @return String
+	 */
+	private String getPath(IPath path, String host) {
+		IPath newPath = path;
+		// They are potentially for only Windows operating system.
+		// a.) if path has a device, and if it begins with IPath.SEPARATOR,
+		// remove it
+		final String device = path.getDevice();
+		if ((device != null) && (device.length() > 0)) {
+			if (device.charAt(0) == IPath.SEPARATOR) {
+				final String newDevice = device.substring(1);
+				newPath = path.setDevice(newDevice);
+			}
+		}
+		// b.) if it has a hostname, it is UNC name... Any java or eclipse api
+		// helps it ??
+		if (path != null && host != null && host.length() != 0) {
+			IPath uncPath = new Path(host);
+			uncPath = uncPath.append(path);
+			newPath = uncPath.makeUNC(true);
+		}
+		return newPath.toString();
+	}
+
+	/**
+	 * 
+	 * @param url
+	 * @return String
+	 */
+	private String getPath(URL url) {
+		String ref = url.getRef() == null ? "" : "#" + url.getRef(); //$NON-NLS-1$ //$NON-NLS-2$
+		String strPath = url.getFile() + ref;
+		IPath path;
+		if (strPath.length() == 0) {
+			path = Path.ROOT;
+		}
+		else {
+			path = new Path(strPath);
+			String query = null;
+			StringTokenizer parser = new StringTokenizer(strPath, "?"); //$NON-NLS-1$
+			int tokenCount = parser.countTokens();
+			if (tokenCount == 2) {
+				path = new Path((String) parser.nextElement());
+				query = (String) parser.nextElement();
+			}
+			if (query == null) {
+				parser = new StringTokenizer(path.toString(), "#"); //$NON-NLS-1$
+				tokenCount = parser.countTokens();
+				if (tokenCount == 2) {
+					path = new Path((String) parser.nextElement());
+				}
+			}
+		}
+		return getPath(path, url.getHost());
+	}
+
+	public org.eclipse.core.resources.IProject getProject() {
+		return fProject;
+	}
+
+	public org.eclipse.core.resources.IContainer getRootLocation() {
+		return fProject;
+	}
+
+	protected String getRootLocationString() {
+		String location = null;
+		if (fProject == null)
+			return null;
+		if (fProject.getLocation() != null) {
+			location = fProject.getLocation().toString();
+		}
+		if (location == null && fProject.getLocationURI() != null) {
+			location = fProject.getLocationURI().toString();
+		}
+		if (location == null) {
+			location = fProject.getFullPath().toString();
+		}
+		return location;
+	}
+
+	public InputStream getURIStream(String uri) {
+		return null;
+	}
+
+	// defect 244817 start
+	/**
+	 * 
+	 * @param passedSpec
+	 * @return boolean
+	 */
+	private boolean isFileURL(String passedSpec) {
+		if (passedSpec == null) {
+			return false;
+		}
+		final String spec = passedSpec.trim();
+		if (spec.length() == 0) {
+			return false;
+		}
+		final int limit = spec.length();
+		String newProtocol = null;
+		for (int index = 0; index < limit; index++) {
+			final char p = spec.charAt(index);
+			if (p == '/') { //$NON-NLS-1$
+				break;
+			}
+			if (p == ':') { //$NON-NLS-1$
+				newProtocol = spec.substring(0, index);
+				break;
+			}
+		}
+		return (newProtocol != null && newProtocol.compareToIgnoreCase("file") == 0); //$NON-NLS-1$
+	}
+
+	public void setFileBaseLocation(String newFileBaseLocation) {
+		fFileBaseLocation = newFileBaseLocation;
+	}
+
+	public void setProject(IProject newProject) {
+		fProject = newProject;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/ResourceUtil.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/ResourceUtil.java
new file mode 100644
index 0000000..ab59ecb
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/ResourceUtil.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.util;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+
+
+/**
+ * @deprecated - makes assumptions on behalf of the requester
+ */
+public class ResourceUtil {
+
+	/**
+	 * Obtains the IFile for a model
+	 * 
+	 * @param model
+	 *            the model to use
+	 * @return the IFile used to create the model, if it came from an IFile,
+	 *         null otherwise
+	 */
+	public static IFile getFileFor(IStructuredModel model) {
+		if (model == null)
+			return null;
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IFile file = null;
+		IPath location = new Path(model.getBaseLocation());
+		// if the path is not a path in the file system and there are at least
+		// 2 segments, it might be in the workspace
+		IFile[] files = root.findFilesForLocation(location);
+		if (files.length > 0) {
+			file = files[0];
+		}
+		else if (location.segmentCount() > 1) {
+			// remember, this IFile isn't guaranteed to exist
+			file = root.getFile(location);
+		}
+		return file;
+	}
+
+	/**
+	 * Obtain IFiles from IStructuredModel (includes linkedResources)
+	 * 
+	 * @return the corresponding files in the workspace, or an empty array if
+	 *         none
+	 */
+	public static IFile[] getFilesFor(IStructuredModel model) {
+		if (model == null)
+			return null;
+
+		IFile[] files = null;
+		IPath location = new Path(model.getBaseLocation());
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		// if the path is not a path in the file system and there are at least
+		// 2 segments, it might be in the workspace
+		if (!location.toFile().exists() && location.segmentCount() > 1) {
+			// remember, this IFile isn't guaranteed to exist
+			files = new IFile[]{root.getFile(location)};
+		}
+		else {
+			files = root.findFilesForLocation(location);
+		}
+		return files;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/ScriptLanguageKeys.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/ScriptLanguageKeys.java
new file mode 100644
index 0000000..d886ba2
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/ScriptLanguageKeys.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2011 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.util;
+
+/**
+ * Contains list of script languages and mime types
+ */
+public interface ScriptLanguageKeys {
+
+	public static final String JAVA = "java"; //$NON-NLS-1$
+
+	public static final String[] JAVA_LANGUAGE_KEYS = new String[]{"java"}; //$NON-NLS-1$
+
+	public static final String JAVASCRIPT = "javascript"; //$NON-NLS-1$
+	public static final String[] JAVASCRIPT_LANGUAGE_KEYS = {"javascript", //$NON-NLS-1$
+				"ecmascript", //$NON-NLS-1$
+				"javascript1.0", //$NON-NLS-1$
+				"javascript1.1", //$NON-NLS-1$
+				"javascript1.2", //$NON-NLS-1$
+				"javascript1.3", //$NON-NLS-1$
+				"javascript1.4", //$NON-NLS-1$
+				"javascript1.5", //$NON-NLS-1$
+				"javascript1.6", //$NON-NLS-1$
+				"jscript", //$NON-NLS-1$
+				"sashscript"}; //$NON-NLS-1$
+
+	public static final String[] JAVASCRIPT_MIME_TYPE_KEYS = {"text/javascript", //$NON-NLS-1$
+				"application/ecmascript", //$NON-NLS-1$
+				"application/javascript", //$NON-NLS-1$
+				"application/x-ecmascript", //$NON-NLS-1$
+				"application/x-javascript", //$NON-NLS-1$
+				"text/ecmascript", //$NON-NLS-1$
+				"text/javascript1.0", //$NON-NLS-1$
+				"text/javascript1.1", //$NON-NLS-1$
+				"text/javascript1.2", //$NON-NLS-1$
+				"text/javascript1.3", //$NON-NLS-1$
+				"text/javascript1.4", //$NON-NLS-1$
+				"text/javascript1.5", //$NON-NLS-1$
+				"text/jscript", //$NON-NLS-1$
+				"text/livescript", //$NON-NLS-1$
+				"text/x-ecmascript", //$NON-NLS-1$
+				"text/x-javascript", //$NON-NLS-1$
+				"text/sashscript"}; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Sorter.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Sorter.java
new file mode 100644
index 0000000..41cdf33
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Sorter.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2009 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.util;
+
+
+
+/**
+ * The SortOperation takes a collection of objects and returns a sorted
+ * collection of these objects. Concrete instances of this class provide the
+ * criteria for the sorting of the objects based on the type of the objects.
+ */
+public abstract class Sorter {
+
+	/**
+	 * Returns true iff elementTwo is 'greater than' elementOne. This is the
+	 * 'ordering' method of the sort operation. Each subclass overrides this
+	 * method with the particular implementation of the 'greater than' concept
+	 * for the objects being sorted. If elementOne and elementTwo are
+	 * equivalent in terms of their sorting order, this method must return
+	 * 'false'.
+	 */
+	public abstract boolean compare(Object elementOne, Object elementTwo);
+
+	/**
+	 * Sort the objects in the array and return the array.
+	 */
+	private Object[] quickSort(Object[] array, int left, int right) {
+		int originalLeft = left;
+		int originalRight = right;
+		Object mid = array[(left + right) / 2];
+
+		do {
+			while (compare(array[left], mid))
+				left++;
+			while (compare(mid, array[right]))
+				right--;
+			if (left <= right) {
+				Object tmp = array[left];
+				array[left] = array[right];
+				array[right] = tmp;
+				left++;
+				right--;
+			}
+		} while (left <= right);
+
+		if (originalLeft < right)
+			array = quickSort(array, originalLeft, right);
+		if (left < originalRight)
+			array = quickSort(array, left, originalRight);
+
+		return array;
+	}
+
+	/**
+	 * Return a new (quick)sorted array from this unsorted array. The original
+	 * array is not modified.
+	 */
+	public Object[] sort(Object[] unSortedCollection) {
+		int size = unSortedCollection.length;
+		Object[] sortedCollection = new Object[size];
+
+		//copy the array so can return a new sorted collection
+		System.arraycopy(unSortedCollection, 0, sortedCollection, 0, size);
+		if (size > 1)
+			quickSort(sortedCollection, 0, size - 1);
+
+		return sortedCollection;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/TextUtilities.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/TextUtilities.java
new file mode 100644
index 0000000..423fa49
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/TextUtilities.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.util;
+
+
+
+/**
+ * Collection of text functions.
+ * @deprecated - the JFace class is public in 3.1
+ */
+// This class was originally copied from org.eclipse.jface.text, and made
+// public
+public class TextUtilities {
+	/**
+	 * Returns whether the text ends with one of the given search strings.
+	 */
+	public static boolean endsWith(String[] searchStrings, String text) {
+		for (int i = 0; i < searchStrings.length; i++) {
+			if (text.endsWith(searchStrings[i]))
+				return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Returns the position in the string greater than offset of the longest
+	 * matching search string.
+	 */
+	public static int[] indexOf(String[] searchStrings, String text, int offset) {
+
+		int[] result = {-1, -1};
+
+		for (int i = 0; i < searchStrings.length; i++) {
+			int index = text.indexOf(searchStrings[i], offset);
+			if (index >= 0) {
+
+				if (result[0] == -1) {
+					result[0] = index;
+					result[1] = i;
+				} else if (index < result[0]) {
+					result[0] = index;
+					result[1] = i;
+				} else if (index == result[0] && searchStrings[i].length() > searchStrings[result[1]].length()) {
+					result[0] = index;
+					result[1] = i;
+				}
+			}
+		}
+
+		return result;
+
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/URIResolver.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/URIResolver.java
new file mode 100644
index 0000000..e2259eb
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/URIResolver.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.util;
+
+import java.io.InputStream;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+
+
+/**
+ * @deprecated
+ * 
+ * Should use extensible URIResolver from org.eclipse.wst.common.uriresolver
+ * instead.
+ */
+
+public interface URIResolver {
+
+	String getFileBaseLocation();
+
+	/**
+	 * Resolve the (possibly relative) URI acording to RFC1808 using the
+	 * default file base location. Resolves resource references into absolute
+	 * resource locations without ensuring that the resource actually exists.
+	 */
+	String getLocationByURI(String uri);
+
+	/**
+	 * Resolve the (possibly relative) URI acording to RFC1808 using the
+	 * default file base location. Resolves resource references into absolute
+	 * resource locations without ensuring that the resource actually exists.
+	 * 
+	 * If resolveCrossProjectLinks is set to true, then this method will
+	 * properly resolve the URI if it is a valid URI to another (appropriate)
+	 * project.
+	 */
+	String getLocationByURI(String uri, boolean resolveCrossProjectLinks);
+
+	/**
+	 * Perform the getLocationByURI action using the baseReference as the
+	 * point of reference instead of the default for this resolver
+	 */
+	String getLocationByURI(String uri, String baseReference);
+
+	/**
+	 * Perform the getLocationByURI action using the baseReference as the
+	 * point of reference instead of the default for this resolver
+	 * 
+	 * If resolveCrossProjectLinks is set to true, then this method will
+	 * properly resolve the URI if it is a valid URI to another (appropriate)
+	 * project.
+	 */
+	String getLocationByURI(String uri, String baseReference, boolean resolveCrossProjectLinks);
+
+	IProject getProject();
+
+	IContainer getRootLocation();
+
+	/**
+	 * Attempts to return a direct inputstream to the given URI which must be
+	 * relative to the default point of reference.
+	 * 
+	 */
+	InputStream getURIStream(String uri);
+
+	void setFileBaseLocation(String newLocation);
+
+	void setProject(IProject newProject);
+
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Utilities.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Utilities.java
new file mode 100644
index 0000000..911c5e9
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Utilities.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.util;
+
+
+
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+
+import org.eclipse.wst.sse.core.internal.encoding.CodedIO;
+import org.eclipse.wst.sse.core.internal.encoding.util.BufferedLimitedStream;
+
+
+
+public class Utilities {
+
+	/**
+	 * a common calculation in some of the parsing methods (e.g. in
+	 * ContextRegion and IStructuredDocumentRegion)
+	 */
+	public static int calculateLengthDifference(String changes, int lengthToReplace) {
+		// determine the length by the text itself, or, if there is no text to
+		// insert (i.e. we are doing a delete) then calculate the length as
+		// a negative number to denote the amount to delete.
+		// For a straight insert, the selection Length will be zero.
+		int lengthDifference = 0;
+		if (changes == null) {
+			// the delete case
+			lengthDifference = 0 - lengthToReplace;
+		}
+		else {
+			lengthDifference = changes.length() - lengthToReplace;
+		}
+		if (Debug.debugStructuredDocument) {
+			System.out.println("lengthDifference: " + lengthDifference);//$NON-NLS-1$
+		}
+		return lengthDifference;
+	}
+
+	/**
+	 * Returns true iff both parameters are not null and the object is within
+	 * the array. Careful, this uses identity. Not good for basic strings.
+	 */
+	public static boolean contains(Object[] objectArray, Object object) {
+		boolean result = false;
+		// if object or objectArray is null, return false
+		if ((objectArray != null) && (object != null)) {
+			for (int i = 0; i < objectArray.length; i++) {
+				if (objectArray[i] == object) {
+					result = true;
+					break;
+				}
+			}
+		}
+		return result;
+	}
+
+	public static boolean containsString(String[] objectArray, String object) {
+		boolean result = false;
+		// if object or objectArray is null, return false
+		if ((objectArray != null) && (object != null)) {
+			for (int i = 0; i < objectArray.length; i++) {
+				if (objectArray[i].equals(object)) {
+					result = true;
+					break;
+				}
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * Ensures that an InputStream has mark/reset support, is readlimit is
+	 * set, and that the stream is "limitable" (that is, reports "end of
+	 * input" rather than allow going past mark). This is very specialized
+	 * stream introduced to overcome
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=67211. See also
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=68565
+	 */
+	public static InputStream getLimitedStream(InputStream original) {
+		if (original == null)
+			return null;
+		if (original instanceof BufferedLimitedStream)
+			return original;
+		return new BufferedLimitedStream(original, CodedIO.MAX_BUF_SIZE);
+	}
+
+	/**
+	 * <p>
+	 * Ensures that an InputStream has mark/reset support.
+	 * </p>
+	 * <p>
+	 * It's vital that a BufferedInputStream <b>not</b> be wrapped in another
+	 * BufferedInputStream as each can preemptively consume <i>n</i> bytes
+	 * (e.g. 2048) from the parent stream before any requests are made. The
+	 * cascading effect is that the second/inner BufferedInputStream can never
+	 * rewind itself to the first <i>n</i> bytes since they were already
+	 * consumed by its parent.
+	 * </p>
+	 */
+	public static InputStream getMarkSupportedStream(InputStream original) {
+		if (original == null)
+			return null;
+		if (original.markSupported())
+			return original;
+		InputStream buffered = new BufferedInputStream(original, CodedIO.MAX_BUF_SIZE);
+		buffered.mark(CodedIO.MAX_MARK_SIZE);
+		return buffered;
+	}
+
+	/**
+	 * Used for log/trace messages. Id is assumed to be some form of a
+	 * filename. See IModelManager.
+	 */
+	public static String makeShortId(Object id) {
+		if (id == null)
+			id = "NOID";//$NON-NLS-1$
+		String whole = id.toString();
+		String part = whole.substring(whole.lastIndexOf("/") + 1); //$NON-NLS-1$
+		return "..." + part; //$NON-NLS-1$
+	}
+
+
+	/**
+	 * Utilities constructor comment.
+	 */
+	public Utilities() {
+		super();
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ErrorInfo.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ErrorInfo.java
new file mode 100644
index 0000000..d36b92c
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ErrorInfo.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 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.wst.sse.core.internal.validate;
+
+
+
+public interface ErrorInfo {
+
+	public String getHint();
+
+	public int getLength();
+
+	public int getOffset();
+
+	public int getState();
+
+	public short getTargetType();
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ValidationAdapter.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ValidationAdapter.java
new file mode 100644
index 0000000..336020e
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ValidationAdapter.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.validate;
+
+
+
+import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
+import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
+
+/**
+ */
+public interface ValidationAdapter extends INodeAdapter {
+
+	/**
+	 */
+	void setReporter(ValidationReporter reporter);
+
+	/**
+	 */
+	void validate(IndexedRegion node);
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ValidationMessage.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ValidationMessage.java
new file mode 100644
index 0000000..5f2f605
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ValidationMessage.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2008 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.validate;
+
+
+
+/**
+ */
+public class ValidationMessage {
+	public static final int IGNORE = -1;
+	public static final int ERROR = 1;
+	public static final int INFORMATION = 3;
+	public static final int WARNING = 2;
+	private int length;
+
+	private String message;
+	private int offset;
+	private int severity;
+
+	/**
+	 */
+	public ValidationMessage(String message, int offset, int severity) {
+		this(message, offset, 0, severity);
+	}
+
+	/**
+	 */
+	public ValidationMessage(String message, int offset, int length, int severity) {
+		super();
+
+		this.message = message;
+		this.offset = offset;
+		this.length = length;
+		this.severity = severity;
+	}
+
+	/**
+	 */
+	public int getLength() {
+		return this.length;
+	}
+
+	/**
+	 */
+	public String getMessage() {
+		return this.message;
+	}
+
+	/**
+	 */
+	public int getOffset() {
+		return this.offset;
+	}
+
+	/**
+	 */
+	public int getSeverity() {
+		return this.severity;
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ValidationReporter.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ValidationReporter.java
new file mode 100644
index 0000000..82a06b5
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ValidationReporter.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.validate;
+
+
+
+
+/**
+ */
+public interface ValidationReporter {
+
+	/**
+	 */
+	void report(ValidationMessage message);
+	
+	void report(ErrorInfo info);
+	
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ValidatorGroupListener.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ValidatorGroupListener.java
new file mode 100644
index 0000000..c34c271
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/validate/ValidatorGroupListener.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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.wst.sse.core.internal.validate;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.wst.sse.core.StructuredModelManager;
+import org.eclipse.wst.sse.core.internal.Logger;
+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
+import org.eclipse.wst.validation.IValidatorGroupListener;
+import org.eclipse.wst.validation.ValidationState;
+
+public class ValidatorGroupListener implements IValidatorGroupListener {
+
+	Map fDiagnosticMap = new HashMap();
+	private static final boolean _debug = false;
+
+	public ValidatorGroupListener() {
+	}
+
+	protected void finalize() throws Throwable {
+		super.finalize();
+		if (fDiagnosticMap != null && !fDiagnosticMap.isEmpty()) {
+			Object[] paths = fDiagnosticMap.keySet().toArray();
+			for (int i = 0; i < paths.length; i++) {
+				Logger.log(Logger.ERROR, "Leaked model: " + paths[i]);
+				validationFinishing(ResourcesPlugin.getWorkspace().getRoot().getFile((IPath) paths[i]), new NullProgressMonitor(), null);
+			}
+		}
+	}
+
+	public void validationFinishing(IResource resource, IProgressMonitor monitor, ValidationState state) {
+		if (_debug)
+			System.out.println("Finishing:" + resource.getFullPath());
+		if (resource.getType() != IResource.FILE)
+			return;
+
+		IStructuredModel model = (IStructuredModel) fDiagnosticMap.remove(resource.getFullPath());
+		if (model != null) {
+			model.releaseFromRead();
+		}
+	}
+
+	public void validationStarting(IResource resource, IProgressMonitor monitor, ValidationState state) {
+		if (_debug)
+			System.out.println("Starting: " + resource.getFullPath());
+		try {
+			if (monitor != null && !monitor.isCanceled()) {
+				if (resource.getType() != IResource.FILE)
+					return;
+
+				IModelManager modelManager = StructuredModelManager.getModelManager();
+				// possible when shutting down
+				if (modelManager != null) {
+					IStructuredModel model = modelManager.getModelForRead((IFile) resource);
+					if (model != null) {
+						fDiagnosticMap.put(resource.getFullPath(), model);
+					}
+				}
+			}
+		}
+		catch (Exception e) {
+			Logger.logException(e);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/text/IStructuredPartitions.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/text/IStructuredPartitions.java
new file mode 100644
index 0000000..e1cfc24
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/text/IStructuredPartitions.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.text;
+
+/**
+ * This interface is not intended to be implemented.
+ * It defines the partitioning for StructuredDocuments.
+ * Clients should reference the partition type Strings defined here directly.
+ * 
+ * @since 1.1
+ */
+public interface IStructuredPartitions {
+
+	String DEFAULT_PARTITION = "org.eclipse.wst.sse.ST_DEFAULT"; //$NON-NLS-1$
+	String UNKNOWN_PARTITION = "org.eclipse.wst.sse.UNKNOWN_PARTITION_TYPE"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/utils/StringUtils.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/utils/StringUtils.java
new file mode 100644
index 0000000..72dca7d
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/utils/StringUtils.java
@@ -0,0 +1,751 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2010 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
+ *     Jens Lukowski/Innoopract - initial renaming/restructuring
+ *     David Carver (Intalio) - bug 300430 - String concatenation
+ *     
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.utils;
+
+
+
+import java.util.ArrayList;
+import java.util.List;
+import com.ibm.icu.util.StringTokenizer;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.wst.sse.core.internal.Logger;
+
+
+public class StringUtils {
+	protected static final String AMPERSTAND = "&"; //$NON-NLS-1$
+	protected static final String AMPERSTAND_ENTITY = "&&;"; //$NON-NLS-1$
+	protected static final String CARRIAGE_RETURN = "\r"; //$NON-NLS-1$
+	protected static final String CARRIAGE_RETURN_ENTITY = "\\r"; //$NON-NLS-1$
+	protected static final String CR = "\r"; //$NON-NLS-1$
+	protected static final String CRLF = "\r\n"; //$NON-NLS-1$
+	protected static final String DELIMITERS = " \t\n\r\f"; //$NON-NLS-1$
+	protected static final String DOUBLE_QUOTE = "\""; //$NON-NLS-1$
+	protected static final char DOUBLE_QUOTE_CHAR = '\"'; //$NON-NLS-1$
+	protected static final String DOUBLE_QUOTE_ENTITY = "&quot;"; //$NON-NLS-1$
+
+	protected static final String EQUAL_SIGN = "="; //$NON-NLS-1$
+	protected static final String EQUAL_SIGN_ENTITY = "&#61;"; //$NON-NLS-1$
+	private static final String FALSE = "false"; //$NON-NLS-1$
+	protected static final String GREATER_THAN = ">"; //$NON-NLS-1$
+	protected static final String GREATER_THAN_ENTITY = "&gt;"; //$NON-NLS-1$
+	protected static final String LESS_THAN = "<"; //$NON-NLS-1$
+	protected static final String LESS_THAN_ENTITY = "&lt;"; //$NON-NLS-1$
+	protected static final String LF = "\n"; //$NON-NLS-1$
+	protected static final String LINE_FEED = "\n"; //$NON-NLS-1$
+	protected static final String LINE_FEED_ENTITY = "\\n"; //$NON-NLS-1$
+	protected static final String LINE_FEED_TAG = "<dl>"; //$NON-NLS-1$
+	protected static final String LINE_TAB = "\t"; //$NON-NLS-1$
+	protected static final String LINE_TAB_ENTITY = "\\t"; //$NON-NLS-1$
+	protected static final String LINE_TAB_TAG = "<dd>"; //$NON-NLS-1$
+	protected static final String SINGLE_QUOTE = "'"; //$NON-NLS-1$
+	protected static final char SINGLE_QUOTE_CHAR = '\''; //$NON-NLS-1$
+	protected static final String SINGLE_QUOTE_ENTITY = "&#039;"; //$NON-NLS-1$
+	protected static final String SPACE = " "; //$NON-NLS-1$
+	protected static final String SPACE_ENTITY = "&nbsp;"; //$NON-NLS-1$
+	private static final String TRUE = "true"; //$NON-NLS-1$
+
+	/**
+	 * Append appendString to the end of aString only if aString does not end
+	 * with the insertString.
+	 */
+	public static String appendIfNotEndWith(String aString, String appendString) {
+		if ((aString != null) && (appendString != null))
+			if (aString.endsWith(appendString))
+				return aString;
+			else
+				return aString + appendString;
+		else
+			return aString;
+	}
+
+	/**
+	 * Breaks out space-separated words into an array of words. For example:
+	 * <code>"no comment"</code> into an array <code>a[0]="no"</code> and
+	 * <code>a[1]= "comment"</code>.
+	 * 
+	 * @param value
+	 *            the string to be converted
+	 * @return the list of words
+	 */
+	public static String[] asArray(String value) {
+		ArrayList list = new ArrayList();
+		StringTokenizer stok = new StringTokenizer(value);
+		while (stok.hasMoreTokens()) {
+			list.add(stok.nextToken());
+		}
+		String result[] = new String[list.size()];
+		list.toArray(result);
+		return result;
+	}
+
+	/**
+	 * Breaks out delim-separated words into an array of words. For example:
+	 * <code>"no comment"</code> into an array <code>a[0]="no"</code> and
+	 * <code>a[1]= "comment"</code>.
+	 * 
+	 * @param value
+	 *            the string to be converted
+	 * @return the list of words
+	 */
+	public static String[] asArray(String value, String delim) {
+		return asArray(value, delim, false);
+	}
+
+	/**
+	 * Breaks out delim-separated words into an array of words. For example:
+	 * <code>"no comment"</code> into an array <code>a[0]="no"</code> and
+	 * <code>a[1]= "comment"</code>.
+	 * 
+	 * @param value
+	 *            the string to be converted
+	 * @return the list of words
+	 */
+	public static String[] asArray(String value, String delim, boolean returnTokens) {
+		ArrayList list = new ArrayList();
+		StringTokenizer stok = new StringTokenizer(value, delim, returnTokens);
+		while (stok.hasMoreTokens()) {
+			list.add(stok.nextToken());
+		}
+		String result[] = new String[list.size()];
+		list.toArray(result);
+		return result;
+	}
+
+	/**
+	 * Breaks out delim-separated words into an array of words. For example:
+	 * <code>"abc,,def"</code> into an array <code>a[0]="abc"</code>,
+	 * <code>a[1]=null</code>, and <code>a[2]= "def"</code> where "," is
+	 * the delim.
+	 * 
+	 * @param value
+	 *            the string to be converted
+	 * @return the list of words
+	 */
+	public static String[] asFixedArray(String value, String delim) {
+		String array[] = asArray(value, delim, true);
+		int arrayLength = array.length;
+		boolean stringFound = false;
+		ArrayList list = new ArrayList();
+
+		for (int i = 0; i < arrayLength; i++) {
+			String token = array[i];
+			if (token.compareTo(delim) == 0) {
+				if (!stringFound)
+					list.add(null);
+				stringFound = false;
+			}
+			else {
+				list.add(token);
+				stringFound = true;
+			}
+		}
+		// add one more null if last token is the delim
+		if (!stringFound)
+			list.add(null);
+
+		String result[] = new String[list.size()];
+		list.toArray(result);
+		return result;
+	}
+
+	public static String chop(String source) {
+		return chop(source, "/"); //$NON-NLS-1$
+	}
+
+	public static String chop(String source, String delimiter) {
+		return source.substring(0, source.lastIndexOf(delimiter));
+	}
+
+	public static boolean contains(String[] arrayOfStrings, String needle, boolean caseSensitive) {
+		boolean result = false;
+		if (needle == null)
+			return false;
+		if (arrayOfStrings == null)
+			return false;
+
+		if (caseSensitive) {
+			for (int i = 0; i < arrayOfStrings.length; i++) {
+				if (needle.equals(arrayOfStrings[i])) {
+					result = true;
+					break;
+				}
+			}
+		}
+		else {
+			for (int i = 0; i < arrayOfStrings.length; i++) {
+				if (needle.equalsIgnoreCase(arrayOfStrings[i])) {
+					result = true;
+					break;
+				}
+			}
+		}
+		return result;
+	}
+
+	public static boolean containsLetters(String fullValue) {
+
+		if (fullValue == null || fullValue.length() == 0)
+			return false;
+
+		char[] chars = fullValue.toCharArray();
+		for (int i = 0; i < fullValue.length(); i++)
+			if (Character.isLetter(chars[i]))
+				return true;
+
+		return false;
+	}
+
+	public static boolean containsLineDelimiter(String aString) {
+		return indexOfLineDelimiter(aString) != -1;
+	}
+
+	public static String convertLineDelimiters(String allText, String lineDelimiterToUse) {
+		IDocument tempDoc = new Document(allText);
+
+		if (lineDelimiterToUse == null)
+			lineDelimiterToUse = System.getProperty("line.separator"); //$NON-NLS-1$
+
+		String newText = ""; //$NON-NLS-1$
+		int lineCount = tempDoc.getNumberOfLines();
+		StringBuffer sb = new StringBuffer(newText);
+		for (int i = 0; i < lineCount; i++) {
+			try {
+				org.eclipse.jface.text.IRegion lineInfo = tempDoc.getLineInformation(i);
+				int lineStartOffset = lineInfo.getOffset();
+				int lineLength = lineInfo.getLength();
+				int lineEndOffset = lineStartOffset + lineLength;
+				sb.append(allText.substring(lineStartOffset, lineEndOffset));
+
+				if ((i < lineCount - 1) && (tempDoc.getLineDelimiter(i) != null)) {
+					sb.append(lineDelimiterToUse);
+				}
+			}
+			catch (BadLocationException e) {
+				// log for now, unless we find reason not to
+				Logger.log(Logger.INFO, e.getMessage());
+			}
+		}
+		newText = sb.toString();
+
+		return newText;
+	}
+
+	/**
+	 * Replaces all instances of special HTML characters with the appropriate
+	 * HTML entity equivalent. WARNING only use this method for strings that
+	 * dont already have HTML-specific items such as tags and entities.
+	 * 
+	 * @param String
+	 *            content String to convert
+	 * 
+	 * @return String the converted string
+	 * @see HTMLPrinter#convertToHTMLContent(String content)
+	 */
+	public static String convertToHTMLContent(String content) {
+		content = replace(content, AMPERSTAND, AMPERSTAND_ENTITY);
+		content = replace(content, LESS_THAN, LESS_THAN_ENTITY);
+		content = replace(content, GREATER_THAN, GREATER_THAN_ENTITY);
+		content = replace(content, LINE_FEED, LINE_FEED_TAG);
+		content = replace(content, LINE_TAB, LINE_TAB_TAG);
+		content = replace(content, SINGLE_QUOTE, SINGLE_QUOTE_ENTITY);
+		content = replace(content, DOUBLE_QUOTE, DOUBLE_QUOTE_ENTITY);
+		content = replace(content, SPACE + SPACE, SPACE_ENTITY + SPACE_ENTITY); // replacing
+		// every
+		// space
+		// would
+		// be
+		// too
+		// much
+		return content;
+	}
+
+	/**
+	 * Converts a string into a form that will not conflict with saving it
+	 * into an INI file
+	 */
+	public static String escape(String normalString) {
+		if (normalString == null)
+			return null;
+		StringBuffer escapedBuffer = new StringBuffer();
+		StringTokenizer toker = new StringTokenizer(normalString, EQUAL_SIGN + LINE_FEED + CARRIAGE_RETURN + LINE_TAB, true);
+		String chunk = null;
+		while (toker.hasMoreTokens()) {
+			chunk = toker.nextToken();
+			if (chunk.equals(EQUAL_SIGN)) {
+				escapedBuffer.append(EQUAL_SIGN_ENTITY);
+			}
+			else if (chunk.equals(LINE_FEED)) {
+				escapedBuffer.append(LINE_FEED_ENTITY);
+			}
+			else if (chunk.equals(CARRIAGE_RETURN)) {
+				escapedBuffer.append(CARRIAGE_RETURN_ENTITY);
+			}
+			else if (chunk.equals(LINE_TAB)) {
+				escapedBuffer.append(LINE_TAB_ENTITY);
+			}
+			else {
+				escapedBuffer.append(chunk);
+			}
+		}
+		return escapedBuffer.toString();
+	}
+
+	/**
+	 * Returns the first line of the given text without a trailing delimiter
+	 * 
+	 * @param text
+	 * @return
+	 */
+	public static String firstLineOf(String text) {
+		if (text == null || text.length() < 1) {
+			return text;
+		}
+		IDocument doc = new Document(text);
+		try {
+			int lineNumber = doc.getLineOfOffset(0);
+			IRegion line = doc.getLineInformation(lineNumber);
+			return doc.get(line.getOffset(), line.getLength());
+		}
+		catch (BadLocationException e) {
+			// do nothing
+		}
+		return text;
+	}
+
+	public static int indexOfLastLineDelimiter(String aString) {
+		return indexOfLastLineDelimiter(aString, aString.length());
+	}
+
+	public static int indexOfLastLineDelimiter(String aString, int offset) {
+		int index = -1;
+
+		if (aString != null && aString.length() > 0) {
+			index = aString.lastIndexOf(CRLF, offset);
+			if (index == -1) {
+				index = aString.lastIndexOf(CR, offset);
+				if (index == -1)
+					index = aString.lastIndexOf(LF, offset);
+			}
+		}
+
+		return index;
+	}
+
+	public static int indexOfLineDelimiter(String aString) {
+		return indexOfLineDelimiter(aString, 0);
+	}
+
+	public static int indexOfLineDelimiter(String aString, int offset) {
+		int index = -1;
+
+		if (aString != null && aString.length() > 0) {
+			index = aString.indexOf(CRLF, offset);
+			if (index == -1) {
+				index = aString.indexOf(CR, offset);
+				if (index == -1)
+					index = aString.indexOf(LF, offset);
+			}
+		}
+
+		return index;
+	}
+
+	public static int indexOfNonblank(String aString) {
+		return indexOfNonblank(aString, 0);
+	}
+
+	public static int indexOfNonblank(String aString, int offset) {
+		int index = -1;
+
+		if (aString != null && aString.length() > 0) {
+			for (int i = offset; i < aString.length(); i++) {
+				if (DELIMITERS.indexOf(aString.substring(i, i + 1)) == -1) {
+					index = i;
+					break;
+				}
+			}
+		}
+
+		return index;
+	}
+
+	/**
+	 * Insert insertString to the beginning of aString only if aString does
+	 * not start with the insertString.
+	 */
+	public static String insertIfNotStartWith(String aString, String insertString) {
+		if ((aString != null) && (insertString != null))
+			if (aString.startsWith(insertString))
+				return aString;
+			else
+				return insertString + aString;
+		else
+			return aString;
+	}
+
+	public static boolean isQuoted(String string) {
+		if ((string == null) || (string.length() < 2))
+			return false;
+
+		int lastIndex = string.length() - 1;
+		char firstChar = string.charAt(0);
+		char lastChar = string.charAt(lastIndex);
+
+		return (((firstChar == SINGLE_QUOTE_CHAR) && (lastChar == SINGLE_QUOTE_CHAR)) || ((firstChar == DOUBLE_QUOTE_CHAR) && (lastChar == DOUBLE_QUOTE_CHAR)));
+	}
+
+	/**
+	 * Unit tests.
+	 * 
+	 * @param args
+	 *            java.lang.String[]
+	 */
+	public static void main(String[] args) {
+		// testPaste();
+		testStripNonLetterDigits();
+	}
+
+	/*
+	 * Returns the merged form of both strings
+	 */
+	public static String merge(String newStart, String newEnd) {
+		String[] regions = overlapRegions(newStart, newEnd);
+		return regions[0] + regions[1] + regions[2];
+	}
+
+	public static int occurrencesOf(String searchString, char targetChar) {
+		int result = 0;
+		int len = searchString.length();
+		for (int i = 0; i < len; i++) {
+			if (targetChar == searchString.charAt(i))
+				result++;
+		}
+		return result;
+	}
+
+	/**
+	 * 
+	 * @return java.lang.String[]
+	 * @param start
+	 *            java.lang.String
+	 * @param end
+	 *            java.lang.String
+	 * 
+	 * Returns a 3 String array containing unique text from the start,
+	 * duplicated text that overlaps the start and end, and the unique text
+	 * from the end.
+	 */
+	private static String[] overlapRegions(String start, String end) {
+		String[] results = null;
+		if (start != null && end == null) {
+			results = new String[]{start, "", ""}; //$NON-NLS-2$//$NON-NLS-1$
+		}
+		else if (start == null && end != null) {
+			results = new String[]{"", "", end}; //$NON-NLS-2$//$NON-NLS-1$
+		}
+		else if (start == null && end == null) {
+			results = new String[]{"", "", ""}; //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+		}
+		else if (start != null && end != null) {
+
+			int startLength = start.length();
+			int endLength = end.length();
+
+			if (startLength == 0 || endLength == 0) {
+				results = new String[]{"", "", ""}; //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+			}
+			else {
+				results = new String[3];
+				String testStart = ""; //$NON-NLS-1$
+				String testEnd = ""; //$NON-NLS-1$
+				int mergeLength = Math.min(startLength, endLength);
+				boolean finished = false;
+				while (mergeLength > 0 && !finished) {
+					testStart = start.substring(startLength - mergeLength);
+					testEnd = end.substring(0, mergeLength);
+					// case sensitive
+					if (testStart.equals(testEnd)) {
+						finished = true;
+						results[0] = start.substring(0, startLength - mergeLength);
+						results[1] = start.substring(startLength - mergeLength);
+						results[2] = end.substring(mergeLength);
+					}
+					mergeLength--;
+				}
+				if (!finished) {
+					results[0] = start;
+					results[1] = ""; //$NON-NLS-1$
+					results[2] = end;
+				}
+			}
+		}
+		return results;
+	}
+
+	/**
+	 * Packs an array of Strings into a single comma delimited String.
+	 * 
+	 * @param strings
+	 * @return
+	 * @todo Generated comment
+	 */
+	public static String pack(String[] strings) {
+		StringBuffer buf = new StringBuffer();
+		for (int i = 0; i < strings.length; i++) {
+			buf.append(StringUtils.replace(strings[i], ",", "&comma;")); //$NON-NLS-1$ //$NON-NLS-2$
+			if (i < strings.length - 1)
+				buf.append(","); //$NON-NLS-1$
+		}
+		return buf.toString();
+	}
+
+	/*
+	 * Pastes the new text into the old at the start position, replacing text
+	 * implied by length.
+	 */
+	public static String paste(String oldText, String newText, int start, int length) {
+		String result = null;
+		StringBuffer sb = new StringBuffer();
+		int startIndex = start;
+		int endIndex = start + length;
+		if (startIndex > oldText.length()) {
+			startIndex = oldText.length();
+		}
+		sb.append(oldText.substring(0, startIndex));
+		// null or empty new text accompliches a delete
+		if (newText != null) {
+			sb.append(newText);
+		}
+		if (endIndex < oldText.length()) {
+
+			sb.append(oldText.substring(endIndex));
+		}
+		result = sb.toString();
+		return result;
+	}
+
+	/**
+	 * Replace matching literal portions of a string with another string
+	 */
+	public static String replace(String aString, String source, String target) {
+		if (aString == null)
+			return null;
+		String normalString = ""; //$NON-NLS-1$
+		int length = aString.length();
+		int position = 0;
+		int previous = 0;
+		int spacer = source.length();
+		StringBuffer sb = new StringBuffer(normalString);
+		while (position + spacer - 1 < length && aString.indexOf(source, position) > -1) {
+			position = aString.indexOf(source, previous);
+			sb.append(normalString);
+			sb.append(aString.substring(previous, position));
+			sb.append(target);
+			position += spacer;
+			previous = position;
+		}
+		sb.append(aString.substring(position, aString.length()));
+		normalString = sb.toString();
+
+		return normalString;
+	}
+
+	/**
+	 * Restore the entity references for markup delimiters in text where they
+	 * have been replaced by the proper Unicode values through a DOM text
+	 * parser.
+	 */
+	public static String restoreMarkers(String text) {
+		String content = text;
+		content = replace(content, AMPERSTAND, AMPERSTAND_ENTITY);
+		content = replace(content, LESS_THAN, LESS_THAN_ENTITY);
+		content = replace(content, GREATER_THAN, GREATER_THAN_ENTITY);
+		return content;
+	}
+
+	/**
+	 * Removes extra whitespace characters and quotes
+	 */
+	public static String strip(String quotedString) {
+		if (quotedString == null || quotedString.length() == 0)
+			return quotedString;
+		String trimmed = quotedString.trim();
+		if (trimmed.length() < 2)
+			return quotedString;
+
+		char first = trimmed.charAt(0);
+		char nextToLast = trimmed.charAt(trimmed.length() - 2);
+		char last = trimmed.charAt(trimmed.length() - 1);
+
+		if ((first == '\"' && last == '\"' && nextToLast != '\\') || (first == '\'' && last == '\'' && nextToLast != '\\')) {
+			return trimmed.substring(1, trimmed.length() - 1);
+		}
+		return trimmed;
+	}
+
+	/**
+	 * This method strips anything from the beginning and end of a string that
+	 * is not a letter or digit. It is used by some encoding detectors to come
+	 * up with the encoding name from illformed input (e.g in <?xml
+	 * encoding="abc?> -- where final quote is left off, the '>' is returned
+	 * with the rest of the attribute value 'abc').
+	 */
+	public static String stripNonLetterDigits(String fullValue) {
+		if (fullValue == null || fullValue.length() == 0)
+			return fullValue;
+		int fullValueLength = fullValue.length();
+		int firstPos = 0;
+		while (firstPos < fullValueLength && !Character.isLetterOrDigit(fullValue.charAt(firstPos))) {
+			firstPos++;
+		}
+		int lastPos = fullValueLength - 1;
+		while (lastPos > firstPos && !Character.isLetterOrDigit(fullValue.charAt(lastPos))) {
+			lastPos--;
+		}
+		String result = fullValue;
+		if (firstPos != 0 || lastPos != fullValueLength) {
+			result = fullValue.substring(firstPos, lastPos + 1);
+		}
+		return result;
+	}
+
+	/**
+	 * Similar to strip, except quotes don't need to match such as "UTF' is
+	 * still stripped of both quotes. (Plus, this one does not detect escaped
+	 * quotes)
+	 */
+	public static String stripQuotes(String quotedValue) {
+		if (quotedValue == null)
+			return null;
+		// normally will never have leading or trailing blanks,
+		// but if it does, we'll do lenient interpretation
+		return stripQuotesLeaveInsideSpace(quotedValue).trim();
+	}
+
+	/**
+	 * Like strip quotes, except leaves the start and end space inside the
+	 * quotes
+	 * 
+	 * @param quotedValue
+	 * @return
+	 */
+	public static String stripQuotesLeaveInsideSpace(String quotedValue) {
+		if (quotedValue == null)
+			return null;
+		// nomally will never have leading or trailing blanks ... but just in
+		// case.
+		String result = quotedValue.trim();
+		int len = result.length();
+		if (len > 0) {
+			char firstChar = result.charAt(0);
+			if ((firstChar == SINGLE_QUOTE_CHAR) || (firstChar == DOUBLE_QUOTE_CHAR)) {
+				result = result.substring(1, len);
+			}
+			len = result.length();
+			if (len > 0) {
+				char lastChar = result.charAt(len - 1);
+				if ((lastChar == SINGLE_QUOTE_CHAR) || (lastChar == DOUBLE_QUOTE_CHAR)) {
+					result = result.substring(0, len - 1);
+				}
+			}
+		}
+		return result;
+	}
+
+	public static void testPaste() {
+		String testString = "The quick brown fox ..."; //$NON-NLS-1$
+		System.out.println(paste(testString, null, 4, 5));
+		System.out.println(paste(testString, null, 4, 6));
+		System.out.println(paste(testString, "", 4, 6)); //$NON-NLS-1$
+		System.out.println(paste(testString, "fast", 4, 6)); //$NON-NLS-1$
+		System.out.println(paste(testString, "fast ", 4, 6)); //$NON-NLS-1$
+		System.out.println(paste(testString, "But ", 0, 0)); //$NON-NLS-1$
+		System.out.println(paste("", "burp", 4, 6)); //$NON-NLS-2$//$NON-NLS-1$
+	}
+
+	public static void testStripNonLetterDigits() {
+		String testString = "abc"; //$NON-NLS-1$
+		System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
+		testString = ""; //$NON-NLS-1$
+		System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
+		testString = "\"abc\""; //$NON-NLS-1$
+		System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
+		testString = "\"ab-c1?"; //$NON-NLS-1$
+		System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
+		testString = "+++"; //$NON-NLS-1$
+		System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
+		testString = "abc="; //$NON-NLS-1$
+		System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
+		testString = "abc "; //$NON-NLS-1$
+		System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
+
+	}
+
+	public static String toString(boolean booleanValue) {
+		if (booleanValue)
+			return TRUE;
+		else
+			return FALSE;
+	}
+
+	/**
+	 * Remove "escaped" chars from a string.
+	 */
+	public static String unescape(String aString) {
+		if (aString == null)
+			return null;
+		String normalString = replace(aString, EQUAL_SIGN_ENTITY, EQUAL_SIGN);
+		normalString = replace(normalString, LINE_FEED_ENTITY, LINE_FEED);
+		normalString = replace(normalString, CARRIAGE_RETURN_ENTITY, CARRIAGE_RETURN);
+		normalString = replace(normalString, LINE_TAB_ENTITY, LINE_TAB);
+		return normalString;
+	}
+
+	public static String uniqueEndOf(String newStart, String newEnd) {
+		String[] regions = overlapRegions(newStart, newEnd);
+		return regions[2];
+	}
+
+	/**
+	 * Unpacks a comma delimited String into an array of Strings
+	 * 
+	 * @param s
+	 * @return
+	 * @todo Generated comment
+	 */
+	public static String[] unpack(String s) {
+		if (s == null)
+			return new String[0];
+		StringTokenizer toker = new StringTokenizer(s, ","); //$NON-NLS-1$
+		List list = new ArrayList();
+		while (toker.hasMoreTokens()) {
+			// since we're separating the values with ',', escape ',' in the
+			// values
+			list.add(StringUtils.replace(toker.nextToken(), "&comma;", ",").trim()); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		return (String[]) list.toArray(new String[0]);
+	}
+
+	/**
+	 * StringUtils constructor comment.
+	 */
+	private StringUtils() {
+		super();
+	}
+
+}