293981 [validation] Attributes do not indicate problems with dynamic content in rtexprvalue attributes
293992 [validation] JSPBatchValidator is taking substantially longer when needed taglibs are not on class path
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveAdapterImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveAdapterImpl.java
index 026c3a7..4c0cc87 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveAdapterImpl.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveAdapterImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2007 IBM Corporation and others.
+ * Copyright (c) 2004, 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
@@ -144,6 +144,7 @@
 	private String cachedLanguage;
 	private String cachedContentType;
 	private INodeNotifier notifierAtCreation;
+	private String elIgnored = null;
 
 	private int firstLanguagePosition = -1;
 	private int firstContentTypePosition = -1;
@@ -700,4 +701,12 @@
 		}
 		return desc;
 	}
+
+	public String getElIgnored() {
+		return elIgnored;
+	}
+
+	public void setElIgnored(String ignored) {
+		elIgnored = ignored;
+	}
 }
\ No newline at end of file
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveWatcherImpl.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveWatcherImpl.java
index 5058785..7d0e8b7 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveWatcherImpl.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/document/PageDirectiveWatcherImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 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
@@ -47,7 +47,11 @@
 			PageDirectiveAdapterImpl pageDirectiveAdapter = (PageDirectiveAdapterImpl) ((IDOMDocument) targetElement.getOwnerDocument()).getAdapterFor(PageDirectiveAdapter.class);
 			pageDirectiveAdapter.changedLanguage(((IndexedRegion) targetElement).getStartOffset(), languageValue);
 		}
-
+		if (target.hasAttribute("isELIgnored")) { //$NON-NLS-1$
+			String elIgnored = target.getAttribute("isELIgnored"); //$NON-NLS-1$
+			PageDirectiveAdapterImpl pageDirectiveAdapter = (PageDirectiveAdapterImpl) ((IDOMDocument) targetElement.getOwnerDocument()).getAdapterFor(PageDirectiveAdapter.class);
+			pageDirectiveAdapter.setElIgnored(elIgnored);
+		}
 
 	}
 
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelper.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelper.java
index f8b9043..19af166 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelper.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelper.java
@@ -94,12 +94,22 @@
 	private Map fTranslationProblems = null;
 	private Set fContainerEntries = null;
 	private IJavaProject fJavaProject;
+	
+	/**
+	 * A cache of class names that the class loader could not find.
+	 * Because the TaglibHelper is destroyed and recreated whenever
+	 * the classpath changes this cache will not become stale when the
+	 * classpath changes.
+	 * See Bug 293992.
+	 */
+	private Set fNotFoundClasses = null;
 
 	public TaglibHelper(IProject project) {
 		setProject(project);
 		fProjectEntries = new HashSet();
 		fContainerEntries = new HashSet();
 		fTranslationProblems = new HashMap();
+		fNotFoundClasses = new HashSet();
 	}
 
 	private boolean isIterationTag(TLDElementDeclaration elementDecl, IStructuredDocument document, ITextRegionCollection customTag, List problems) {
@@ -109,11 +119,19 @@
 
 		Class tagClass;
 		try {
-			tagClass = Class.forName(className, true, getClassloader());
-			if (tagClass != null) {
-				return IterationTag.class.isInstance(tagClass.newInstance());
-			}
+			/* check to be sure the class name is not one that can not currently be found on
+			 * the class path.
+			 */
+			if(!fNotFoundClasses.contains(className)) {
+				tagClass = Class.forName(className, true, getClassloader());
+				if (tagClass != null) {
+					return IterationTag.class.isInstance(tagClass.newInstance());
+				}
+			} 
 		} catch (ClassNotFoundException e) {
+			//the class could not be found so add it to the cache
+			fNotFoundClasses.add(className);
+			
 			Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TagClassNotFound, JSPCoreMessages.TaglibHelper_3, className, true);
 			if (createdProblem != null)
 				problems.add(createdProblem);
@@ -341,11 +359,15 @@
 
 		Class teiClass = null;
 		try {
-			/*
-			 * JDT could tell us about it, but loading and calling it would
-			 * still take time
+			/* check to be sure the class name is not one that can not currently be found on
+			 * the class path.
 			 */
-			teiClass = Class.forName(teiClassname, true, loader);
+			if(!fNotFoundClasses.contains(teiClassname)) {
+				/* JDT could tell us about it, but loading and calling it would
+				 * still take time
+				 */
+				teiClass = Class.forName(teiClassname, true, loader);
+			}
 			if (teiClass != null) {
 				Object teiObject = teiClass.newInstance();
 				if (TagExtraInfo.class.isInstance(teiObject)) {
@@ -389,6 +411,9 @@
 			}
 		}
 		catch (ClassNotFoundException e) {
+			//the class could not be found so add it to the cache
+			fNotFoundClasses.add(teiClassname);
+			
 			Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TEIClassNotFound, JSPCoreMessages.TaglibHelper_0, teiClassname, true);
 			if (createdProblem != null) {
 				problems.add(createdProblem);
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 51f0c3d..98ead00 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008 IBM Corporation and others.
+ * Copyright (c) 2008, 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
@@ -16,6 +16,7 @@
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.preferences.DefaultScope;
 import org.eclipse.core.runtime.preferences.IPreferencesService;
@@ -29,9 +30,15 @@
 import org.eclipse.jst.jsp.core.internal.contentmodel.TaglibController;
 import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TLDCMDocumentManager;
 import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TaglibTracker;
+import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDAttributeDeclaration;
+import org.eclipse.jst.jsp.core.internal.contenttype.DeploymentDescriptorPropertyCache;
+import org.eclipse.jst.jsp.core.internal.contenttype.DeploymentDescriptorPropertyCache.PropertyGroup;
+import org.eclipse.jst.jsp.core.internal.document.PageDirectiveAdapter;
+import org.eclipse.jst.jsp.core.internal.document.PageDirectiveAdapterImpl;
 import org.eclipse.jst.jsp.core.internal.preferences.JSPCorePreferenceNames;
 import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
 import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.html.core.internal.HTMLCoreMessages;
 import org.eclipse.wst.sse.core.StructuredModelManager;
 import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
 import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
@@ -53,6 +60,7 @@
 import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
 import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
 import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
 import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
 import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
 import org.w3c.dom.Attr;
@@ -78,6 +86,7 @@
 	private int fSeverityUnknownAttribute = IMessage.NORMAL_SEVERITY;
 
 	private HashSet fTaglibPrefixes = new HashSet();
+	private boolean fIsELIgnored = false;
 
 	public JSPActionValidator() {
 		this.fMessageOriginator = this;
@@ -102,6 +111,48 @@
 		}
 	}
 
+	/**
+	 * Checks an attribute for runtime expressions
+	 * @param a The attribute to check for runtime expressions
+	 * @return true if the attribute contains a runtime expression, false otherwise
+	 */
+	private boolean checkRuntimeValue(IDOMAttr a) {
+		ITextRegion value = a.getValueRegion();
+		if (value instanceof ITextRegionContainer) {
+			Iterator it = ((ITextRegionContainer) value).getRegions().iterator();
+			while (it.hasNext()) {
+				String type = ((ITextRegion) it.next()).getType();
+				if (type == DOMJSPRegionContexts.JSP_EL_OPEN || type == DOMJSPRegionContexts.JSP_VBL_OPEN)
+					return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Determines if EL should be ignored. Checks
+	 * <ol>
+	 *  <li>JSP version</li>
+	 * 	<li>Page directive isELIgnored</li>
+	 *  <li>Deployment descriptor's el-ignored</li>
+	 * </ol>
+	 * @return true if EL should be ignored, false otherwise. If the JSP version is < 2.0, EL is ignored by default
+	 */
+	private boolean isElIgnored(IPath path, IStructuredModel model) {
+		if (DeploymentDescriptorPropertyCache.getInstance().getJSPVersion(path) < 2.0f)
+			return true;
+		String directiveIsELIgnored = ((PageDirectiveAdapterImpl)(((IDOMModel) model).getDocument().getAdapterFor(PageDirectiveAdapter.class))).getElIgnored();
+		// isELIgnored directive found
+		if (directiveIsELIgnored != null)
+			return Boolean.valueOf(directiveIsELIgnored).booleanValue();
+		// Check the deployment descriptor for el-ignored
+		PropertyGroup[] groups = DeploymentDescriptorPropertyCache.getInstance().getPropertyGroups(path);
+		if (groups.length > 0)
+			return groups[0].isELignored();
+		// JSP version >= 2.0 defaults to evaluating EL
+		return false;
+	}
+
 	private void checkRequiredAttributes(IDOMElement element, CMNamedNodeMap attrMap, IReporter reporter, IFile file, IStructuredDocument document, IStructuredDocumentRegion documentRegion) {
 		Iterator it = attrMap.iterator();
 		CMAttributeDeclaration attr = null;
@@ -182,6 +233,26 @@
 					foundjspattribute = true;
 				}
 			}
+			else {
+				if (adec instanceof TLDAttributeDeclaration) {
+					// The attribute cannot have a runtime evaluation of an expression
+					if (!Boolean.valueOf(((TLDAttributeDeclaration) adec).getRtexprvalue()).booleanValue()) {
+						IDOMAttr attr = (IDOMAttr) a;
+						if(checkRuntimeValue(attr) && !fIsELIgnored) {
+							String msg = NLS.bind(HTMLCoreMessages.Invalid_attribute___0____ERROR_, a.getName());
+							LocalizedMessage message = new LocalizedMessage(IMessage.NORMAL_SEVERITY, msg, file);
+							ITextRegion region = attr.getValueRegion();
+							int start = attr.getValueRegionStartOffset();
+							int length = region != null ? region.getTextLength() : 0;
+							int lineNo = document.getLineOfOffset(start);
+							message.setLineNo(lineNo);
+							message.setOffset(start);
+							message.setLength(length);
+							reporter.addMessage(fMessageOriginator, message);
+						}
+					}
+				}
+			}
 		}
 		return foundjspattribute;
 	}
@@ -294,7 +365,7 @@
 	protected void performValidation(IFile f, IReporter reporter, IStructuredModel model, IRegion validateRegion) {
 		loadPreferences(f);
 		IStructuredDocument sDoc = model.getStructuredDocument();
-
+		fIsELIgnored = isElIgnored(f.getFullPath(), model);
 		// iterate all document regions
 		IStructuredDocumentRegion region = sDoc.getRegionAtCharacterOffset(validateRegion.getOffset());
 		while (region != null && !reporter.isCancelled() && (region.getStartOffset() <= (validateRegion.getOffset() + validateRegion.getLength()))) {