sync changes from HEAD
diff --git a/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/HeadParsers/JSPHeadTokenizer.jFlex b/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/HeadParsers/JSPHeadTokenizer.jFlex
index 858dd29..680b15b 100644
--- a/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/HeadParsers/JSPHeadTokenizer.jFlex
+++ b/bundles/org.eclipse.jst.jsp.core/DevTimeSupport/HeadParsers/JSPHeadTokenizer.jFlex
@@ -1,307 +1,305 @@
-/*******************************************************************************
- * Copyright (c) 2005, 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
- *******************************************************************************/
-/*nlsXXX*/
-package org.eclipse.jst.jsp.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;
-        private boolean isXHTML;
-        private boolean isWML;
-
-
-        public JSPHeadTokenizer() {
-                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;
-                isXHTML=false;
-                isWML=false;
-
-
-        }
-
-
-        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);
-        }
-        
-        public boolean isXHTML() {
-            return isXHTML;
-        }
-        public boolean isWML() {
-            return isWML;
-        }        
-
-%}
-
-%eof{
-        hasMore=false;
-%eof}
-
-%public
-%class JSPHeadTokenizer
-%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]
-
-BeginAttributeeValue = {S}* \= {S}*
-
-LineTerminator = \r|\n
-
-
-%state ST_XMLDecl
-%state ST_PAGE_DIRECTIVE
-%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;}}
-
-
-        // following are some simply rules to identify JSP content as "XHTML"
-        // see http://www.rfc-editor.org/rfc/rfc3236.txt
-        "<!DOCTYPE" {S}* "html" {S}* "PUBLIC" .* "//DTD XHTML"                {isXHTML = true;}
-        "<html" {S}* "xmlns" {S}* "=" {S}* (\" | \') "http://www.w3.org/1999/xhtml"     {isXHTML = true;}
-         // another case that's part of the "HTML family" is WML 1.0 (WML 2.0 is part of XHTML)
-         "<!DOCTYPE" {S}* "wml" {S}* "PUBLIC" .* "//DTD WML"                   {isWML = true;}
-
-        "<%" {S}* "@" {S}* ("page"|"tag") {S}+   {yybegin(ST_PAGE_DIRECTIVE); return JSPHeadTokenizerConstants.PageDirectiveStart;}
-        ("<jsp:directive.page"|"<jsp:directive.tag") {S}+           {yybegin(ST_PAGE_DIRECTIVE); return JSPHeadTokenizerConstants.PageDirectiveStart;}
-
-
-}
-
-<ST_XMLDecl>
-{
-        "version" {BeginAttributeeValue} {pushCurrentState(); yybegin(QuotedAttributeValue); return XMLHeadTokenizerConstants.XMLDeclVersion;}
-        "encoding" {BeginAttributeeValue} {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).
-        // BUT, the hasMore=false was removed for this JSP case (probably still ok for pure XML) because
-        // in a JSP, we must parse past xmlDecl to get at JSP page directive.
-        // We'll assume all chars in this area are "readable" as is.
-        {S}* "\?>"    {yybegin(YYINITIAL); return XMLHeadTokenizerConstants.XMLDeclEnd;}
-}
-
-<ST_PAGE_DIRECTIVE>
-{
-//  removed 'language' since it really can be handled seperately from encoding, but may add it back later for simple re-use.
-        "language"     {BeginAttributeeValue} {pushCurrentState(); yybegin(QuotedAttributeValue); return JSPHeadTokenizerConstants.PageLanguage;}
-        "contentType" {BeginAttributeeValue}  {pushCurrentState(); yybegin(QuotedAttributeValue); return JSPHeadTokenizerConstants.PageContentType;}
-        "pageEncoding" {BeginAttributeeValue} {pushCurrentState(); yybegin(QuotedAttributeValue); return JSPHeadTokenizerConstants.PageEncoding;}
-        // 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 in correct encoding.
-
-        // https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=4205 demonstrates how we need to keep parsing,
-        // even if come to end of one page directive, so hasMore=false was removed from these rules.
-        "%>"    { yybegin(YYINITIAL);  return JSPHeadTokenizerConstants.PageDirectiveEnd;}
-        "\/>"    { yybegin(YYINITIAL); return JSPHeadTokenizerConstants.PageDirectiveEnd;}
-}
-
-
-<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() ); }
-
-        "%>"                    { yypushback(2);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}
-
-
-}
-
-<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() ); }
-        "%>"                    { yypushback(2);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}
-
-
-}
-
-<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() ); }
-        "%>"                    { yypushback(2);popState(); valueText = string.toString(); return EncodingParserConstants.InvalidTerminatedStringValue;}
-
-}
-
-// 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, ST_PAGE_DIRECTIVE>
-{
-// 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;}
-
+/*******************************************************************************

+ * Copyright (c) 2005, 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.jst.jsp.core.internal.contenttype;

+import java.io.IOException;

+import java.io.Reader;

+import java.util.Arrays;

+

+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;

+        private boolean isXHTML;

+        private boolean isWML;

+

+

+        public JSPHeadTokenizer() {

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

+                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;

+                isXHTML=false;

+                isWML=false;

+

+

+        }

+

+

+        public final HeadParserToken getNextToken() throws IOException, Exception {

+                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);

+        }

+        

+        public boolean isXHTML() {

+            return isXHTML;

+        }

+        public boolean isWML() {

+            return isWML;

+        }        

+

+%}

+

+%eof{

+        hasMore=false;

+%eof}

+

+%public

+%class JSPHeadTokenizer

+%function primGetNextToken

+%type String

+%char

+%unicode

+%ignorecase

+//%debug

+%switch

+%buffer 8192

+%scanerror java.lang.Exception

+

+

+UTF16BE = \xFE\xFF

+UTF16LE = \xFF\xFE

+UTF83ByteBOM = \xEF\xBB\xBF

+

+// SpaceChar = [\x20\x09]

+

+

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

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

+

+BeginAttributeeValue = {S}* \= {S}*

+

+LineTerminator = \r|\n

+

+

+%state ST_XMLDecl

+%state ST_PAGE_DIRECTIVE

+%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;}}

+

+

+        // following are some simply rules to identify JSP content as "XHTML"

+        // see http://www.rfc-editor.org/rfc/rfc3236.txt

+        "<!DOCTYPE" {S}* "html" {S}* "PUBLIC" .* "//DTD XHTML"                {isXHTML = true;}

+        "<html" {S}* "xmlns" {S}* "=" {S}* (\" | \') "http://www.w3.org/1999/xhtml"     {isXHTML = true;}

+         // another case that's part of the "HTML family" is WML 1.0 (WML 2.0 is part of XHTML)

+         "<!DOCTYPE" {S}* "wml" {S}* "PUBLIC" .* "//DTD WML"                   {isWML = true;}

+

+        "<%" {S}* "@" {S}* ("page"|"tag") {S}+   {yybegin(ST_PAGE_DIRECTIVE); return JSPHeadTokenizerConstants.PageDirectiveStart;}

+        ("<jsp:directive.page"|"<jsp:directive.tag") {S}+           {yybegin(ST_PAGE_DIRECTIVE); return JSPHeadTokenizerConstants.PageDirectiveStart;}

+

+

+}

+

+<ST_XMLDecl>

+{

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

+        "encoding" {BeginAttributeeValue} {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).

+        // BUT, the hasMore=false was removed for this JSP case (probably still ok for pure XML) because

+        // in a JSP, we must parse past xmlDecl to get at JSP page directive.

+        // We'll assume all chars in this area are "readable" as is.

+        {S}* "\?>"    {yybegin(YYINITIAL); return XMLHeadTokenizerConstants.XMLDeclEnd;}

+}

+

+<ST_PAGE_DIRECTIVE>

+{

+//  removed 'language' since it really can be handled seperately from encoding, but may add it back later for simple re-use.

+        "language"     {BeginAttributeeValue} {pushCurrentState(); yybegin(QuotedAttributeValue); return JSPHeadTokenizerConstants.PageLanguage;}

+        "contentType" {BeginAttributeeValue}  {pushCurrentState(); yybegin(QuotedAttributeValue); return JSPHeadTokenizerConstants.PageContentType;}

+        "pageEncoding" {BeginAttributeeValue} {pushCurrentState(); yybegin(QuotedAttributeValue); return JSPHeadTokenizerConstants.PageEncoding;}

+        // 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 in correct encoding.

+

+        // https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=4205 demonstrates how we need to keep parsing,

+        // even if come to end of one page directive, so hasMore=false was removed from these rules.

+        "%>"    { yybegin(YYINITIAL);  return JSPHeadTokenizerConstants.PageDirectiveEnd;}

+        "\/>"    { yybegin(YYINITIAL); return JSPHeadTokenizerConstants.PageDirectiveEnd;}

+}

+

+

+<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() ); }

+

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

+

+

+}

+

+<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() ); }

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

+

+

+}

+

+<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() ); }

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

+

+}

+

+// 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, ST_PAGE_DIRECTIVE>

+{

+// 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;}

+

diff --git a/bundles/org.eclipse.jst.jsp.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.jst.jsp.core/META-INF/MANIFEST.MF
index 113bcfb..2d66309 100644
--- a/bundles/org.eclipse.jst.jsp.core/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.jst.jsp.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jst.jsp.core; singleton:=true
-Bundle-Version: 1.2.100.qualifier
+Bundle-Version: 1.2.101.qualifier
 Bundle-Activator: org.eclipse.jst.jsp.core.internal.JSPCorePlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDCMDocumentManager.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDCMDocumentManager.java
index f9da3ba..b392a68 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDCMDocumentManager.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contentmodel/tld/TLDCMDocumentManager.java
@@ -12,7 +12,7 @@
 
 import java.io.File;
 import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
+import java.lang.ref.SoftReference;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Hashtable;
@@ -663,7 +663,7 @@
 					TLDCacheEntry entry = (TLDCacheEntry) o;
 					entry.referenceCount--;
 					if (entry.referenceCount <= 0) {
-						getSharedDocumentCache().put(key, new WeakReference(entry));
+						getSharedDocumentCache().put(key, new SoftReference(entry));
 					}
 				}
 			}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/DeploymentDescriptorPropertyCache.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/DeploymentDescriptorPropertyCache.java
index ca1289f..7802c77 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/DeploymentDescriptorPropertyCache.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/DeploymentDescriptorPropertyCache.java
@@ -234,10 +234,14 @@
 				return;
 			if (delta.getKind() == IResourceDelta.CHANGED && (delta.getFlags() == IResourceDelta.ENCODING || delta.getFlags() == IResourceDelta.MARKERS))
 				return;
+
 			IResourceDeltaVisitor visitor = new IResourceDeltaVisitor() {
 				public boolean visit(IResourceDelta delta) {
 					IResource resource = delta.getResource();
 					if (resource.getType() == IResource.FILE) {
+						if (delta.getKind() == IResourceDelta.CHANGED && (delta.getFlags() == IResourceDelta.ENCODING || delta.getFlags() == IResourceDelta.MARKERS))
+							return false;
+						
 						IPath path = resource.getFullPath();
 						int segmentCount = path.segmentCount();
 						if (segmentCount > 1 && path.lastSegment().equals(WEB_XML) && path.segment(segmentCount - 2).equals(WEB_INF)) {
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPHeadTokenizer.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPHeadTokenizer.java
index a7f549b..45ae051 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPHeadTokenizer.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPHeadTokenizer.java
@@ -1,5 +1,7 @@
+/* The following code was generated by JFlex 1.4.2 on 6/30/08 4:51 PM */
+
 /*******************************************************************************
- * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * Copyright (c) 2005, 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
@@ -12,19 +14,15 @@
 package org.eclipse.jst.jsp.core.internal.contenttype;
 import java.io.IOException;
 import java.io.Reader;
+import java.util.Arrays;
 
 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.jflex.de/">JFlex</a> 1.4.1
- * on 4/17/07 12:35 AM from the specification file
+ * <a href="http://www.jflex.de/">JFlex</a> 1.4.2
+ * on 6/30/08 4:51 PM from the specification file
  * <tt>D:/eclipse.wtp/workspace/org.eclipse.jst.jsp.core/DevTimeSupport/HeadParsers/JSPHeadTokenizer.jFlex</tt>
  */
 public class JSPHeadTokenizer {
@@ -135,9 +133,6 @@
   /** 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;
 
@@ -193,13 +188,13 @@
 
                 /* this buffer contains the current text to be matched and is
                  the source of the yytext() string */
-                java.util.Arrays.fill(zzBuffer, (char)0);
+                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;
+                //zzPushbackPos = 0;
 
                 /* the current text position in the buffer */
                 zzCurrentPos = 0;
@@ -248,7 +243,7 @@
         }
 
 
-        public final HeadParserToken getNextToken() throws IOException {
+        public final HeadParserToken getNextToken() throws IOException, Exception {
                 String context = null;
                 context = primGetNextToken();
                 HeadParserToken result = null;
@@ -343,7 +338,6 @@
       zzEndRead-= zzStartRead;
       zzCurrentPos-= zzStartRead;
       zzMarkedPos-= zzStartRead;
-      zzPushbackPos-= zzStartRead;
       zzStartRead = 0;
     }
 
@@ -359,13 +353,23 @@
     int numRead = zzReader.read(zzBuffer, zzEndRead,
                                             zzBuffer.length-zzEndRead);
 
-    if (numRead < 0) {
-      return true;
-    }
-    else {
+    if (numRead > 0) {
       zzEndRead+= numRead;
       return false;
     }
+    // unlikely but not impossible: read 0 characters, but not at end of stream    
+    if (numRead == 0) {
+      int c = zzReader.read();
+      if (c == -1) {
+        return true;
+      } else {
+        zzBuffer[zzEndRead++] = (char) c;
+        return false;
+      }     
+    }
+
+	// numRead < 0
+    return true;
   }
 
     
@@ -396,7 +400,7 @@
     zzAtBOL  = true;
     zzAtEOF  = false;
     zzEndRead = zzStartRead = 0;
-    zzCurrentPos = zzMarkedPos = zzPushbackPos = 0;
+    zzCurrentPos = zzMarkedPos = 0;
     yychar = 0;
     zzLexicalState = YYINITIAL;
   }
@@ -466,7 +470,7 @@
    *
    * @param   errorCode  the code of the errormessage to display
    */
-  private void zzScanError(int errorCode) {
+  private void zzScanError(int errorCode) throws java.lang.Exception {
     String message;
     try {
       message = ZZ_ERROR_MSG[errorCode];
@@ -475,7 +479,7 @@
       message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
     }
 
-    throw new Error(message);
+    throw new java.lang.Exception(message);
   } 
 
 
@@ -487,7 +491,7 @@
    * @param number  the number of characters to be read again.
    *                This number must not be greater than yylength()!
    */
-  public void yypushback(int number)  {
+  public void yypushback(int number)  throws java.lang.Exception {
     if ( number > yylength() )
       zzScanError(ZZ_PUSHBACK_2BIG);
 
@@ -515,7 +519,7 @@
    * @return      the next token
    * @exception   java.io.IOException  if any I/O-Error occurs
    */
-  public String primGetNextToken() throws java.io.IOException {
+  public String primGetNextToken() throws java.io.IOException, java.lang.Exception {
     int zzInput;
     int zzAction;
 
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPResourceEncodingDetector.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPResourceEncodingDetector.java
index 5323479..d8292cd 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPResourceEncodingDetector.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/contenttype/JSPResourceEncodingDetector.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * 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
@@ -22,6 +22,7 @@
 
 import org.eclipse.core.resources.IStorage;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jst.jsp.core.internal.Logger;
 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;
@@ -377,7 +378,7 @@
 	 * responsibility of the tokenizer to stop when appropriate and not go too
 	 * far.
 	 */
-	private void parseHeader(JSPHeadTokenizer tokenizer) throws IOException {
+	private void parseHeader(JSPHeadTokenizer tokenizer) throws Exception {
 		fPageEncodingValue = null;
 		fCharset = null;
 
@@ -389,7 +390,6 @@
 			if (canHandleAsUnicodeStream(tokenType))
 				unicodeCase = true;
 			else {
-
 				if (tokenType == XMLHeadTokenizerConstants.XMLDelEncoding) {
 					if (tokenizer.hasMoreTokens()) {
 						HeadParserToken valueToken = tokenizer.getNextToken();
@@ -438,21 +438,23 @@
 		if (tokenizer.isWML() ) {
 			fWML = true;
 		}
-		
-
 	}
 
 	private void parseInput() throws IOException {
 		JSPHeadTokenizer tokenizer = getTokinizer();
 		fReader.reset();
 		tokenizer.reset(fReader);
-		parseHeader(tokenizer);
-		// unicode stream cases are created directly in parseHeader
-		if (!unicodeCase) {
-			String enc = getAppropriateEncoding();
-			if (enc != null && enc.length() > 0) {
-				createEncodingMemento(enc, EncodingMemento.FOUND_ENCODING_IN_CONTENT);
+		try {
+			parseHeader(tokenizer);
+			// unicode stream cases are created directly in parseHeader
+			if (!unicodeCase) {
+				String enc = getAppropriateEncoding();
+				if (enc != null && enc.length() > 0) {
+					createEncodingMemento(enc, EncodingMemento.FOUND_ENCODING_IN_CONTENT);
+				}
 			}
+		} catch (Exception e) {
+			Logger.log(Logger.ERROR_DEBUG, e.getMessage());
 		}
 	}
 
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPActionValidator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPActionValidator.java
index e9cb19e..51f0c3d 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPActionValidator.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/validation/JSPActionValidator.java
@@ -56,7 +56,9 @@
 import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
 import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
 import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.NodeList;
 
 /**
  * Checks for: missing required attributes & undefined attributes in jsp
@@ -108,20 +110,50 @@
 			if (attr.getUsage() == CMAttributeDeclaration.REQUIRED) {
 				Attr a = element.getAttributeNode(attr.getAttrName());
 				if (a == null) {
-					String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_5, attr.getAttrName());
-					LocalizedMessage message = new LocalizedMessage(fSeverityMissingRequiredAttribute, msgText, file);
-					int start = element.getStartOffset();
-					int length = element.getStartEndOffset() - start;
-					int lineNo = document.getLineOfOffset(start);
-					message.setLineNo(lineNo);
-					message.setOffset(start);
-					message.setLength(length);
-
-					reporter.addMessage(fMessageOriginator, message);
+					// Attribute may be defined using a jsp:attribute action
+					if (!checkJSPAttributeAction(element, attr)) {
+						String msgText = NLS.bind(JSPCoreMessages.JSPDirectiveValidator_5, attr.getAttrName());
+						LocalizedMessage message = new LocalizedMessage(fSeverityMissingRequiredAttribute, msgText, file);
+						int start = element.getStartOffset();
+						int length = element.getStartEndOffset() - start;
+						int lineNo = document.getLineOfOffset(start);
+						message.setLineNo(lineNo);
+						message.setOffset(start);
+						message.setLength(length);
+	
+						reporter.addMessage(fMessageOriginator, message);
+					}
 				}
 			}
 		}
 	}
+	
+	/**
+	 * Checks for jsp:attribute actions of <code>element</code> to see if they
+	 * satisfy the required attribute <code>attr</code>
+	 * 
+	 * @param element The element with a required attribute
+	 * @param attr The required attribute
+	 * @return <code>true</code> if a jsp:attribute action has the name of
+	 * the required attribute <code>attr</code>; <code>false</code> otherwise.
+	 */
+	private boolean checkJSPAttributeAction(IDOMElement element, CMAttributeDeclaration attr) {
+		if (element != null && attr != null) {
+			NodeList elements = element.getElementsByTagName("jsp:attribute"); //$NON-NLS-1$
+			String neededAttrName = attr.getNodeName();
+			for (int i = 0; i < elements.getLength(); i++) {
+				Element childElement = (Element) elements.item(i);
+				/*
+				 * Get the name attribute of jsp:attribute and compare its
+				 * value to the required attribute name
+				 */
+				if (neededAttrName.equals(childElement.getAttribute("name"))) {//$NON-NLS-1$
+					return true;
+				}
+			}
+		}
+		return false;
+	}
 
 	private boolean checkUnknownAttributes(IDOMElement element, CMNamedNodeMap cmAttrs, IReporter reporter, IFile file, IStructuredDocument document, IStructuredDocumentRegion documentRegion) {
 		boolean foundjspattribute = false;