[204990] JSP/Web Page Editors: tag files do not support content assist on html element attributes
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/ModelQueryAdapterFactoryForTag.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/ModelQueryAdapterFactoryForTag.java
index 443c8eb..b8874d0 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/ModelQueryAdapterFactoryForTag.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/ModelQueryAdapterFactoryForTag.java
@@ -15,7 +15,6 @@
 import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
 import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
 import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
-import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.ModelQueryImpl;
 import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.SimpleAssociationProvider;
 
 public class ModelQueryAdapterFactoryForTag extends ModelQueryAdapterFactoryForJSP {
@@ -32,6 +31,6 @@
 	}
 
 	ModelQuery createModelQuery(IStructuredModel model, URIResolver resolver) {
-		return new ModelQueryImpl(new SimpleAssociationProvider(new TagModelQueryCMProvider()));
+		return new TagModelQuery(new SimpleAssociationProvider(new TagModelQueryCMProvider()));
 	}
 }
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TagModelQuery.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TagModelQuery.java
new file mode 100644
index 0000000..6adfe2e
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TagModelQuery.java
@@ -0,0 +1,142 @@
+/*******************************************************************************

+ * 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.jst.jsp.core.internal.modelquery;

+

+import java.util.List;

+

+import org.eclipse.core.resources.ProjectScope;

+import org.eclipse.core.resources.ResourcesPlugin;

+import org.eclipse.core.runtime.IPath;

+import org.eclipse.core.runtime.Path;

+import org.eclipse.core.runtime.preferences.IEclipsePreferences;

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

+import org.eclipse.wst.sse.core.internal.ltk.modelhandler.EmbeddedTypeHandler;

+import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerUtility;

+import org.eclipse.wst.sse.core.internal.provisional.IModelManager;

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

+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;

+import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;

+import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;

+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;

+import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryAssociationProvider;

+import org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.ModelQueryImpl;

+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;

+import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter;

+import org.w3c.dom.Element;

+import org.w3c.dom.Node;

+

+/**

+ * ModelQuery for JSP Tag files. Prioritizes the Tag content model and any

+ * loaded tag libraries in the model before falling back to the embedded model

+ * query, if one is found.

+ */

+public class TagModelQuery extends ModelQueryImpl implements ModelQuery {

+	/**

+	 * The default mime-type for the embedded ModelQuery

+	 */

+	public static final String DEFAULT_MIMETYPE = "text/html";

+

+

+	/**

+	 * The prefix used with ProjectScope to find the (possibly user-set)

+	 * embedded mime-type on a .tag file.

+	 */

+	private static final String PREFERENCE_PREFIX = "embeddedMimeType/";

+

+	public static String createPreferenceKey(IPath fullPath) {

+		return PREFERENCE_PREFIX + fullPath.removeFirstSegments(1).toString();

+	}

+

+	private ModelQuery fEmbeddedModelQuery;

+

+	/**

+	 * @param modelQueryAssociationProvider

+	 */

+	public TagModelQuery(ModelQueryAssociationProvider modelQueryAssociationProvider) {

+		super(modelQueryAssociationProvider);

+	}

+

+	/*

+	 * (non-Javadoc)

+	 * 

+	 * @seeorg.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.

+	 * ModelQueryImpl#getCMElementDeclaration(org.w3c.dom.Element)

+	 */

+	public CMElementDeclaration getCMElementDeclaration(Element element) {

+		CMElementDeclaration cmElementDeclaration = super.getCMElementDeclaration(element);

+		if (cmElementDeclaration == null) {

+			ModelQuery embeddedModelQuery = getEmbeddedModelQuery(element);

+			if (embeddedModelQuery != null) {

+				return embeddedModelQuery.getCMElementDeclaration(element);

+			}

+		}

+		return cmElementDeclaration;

+	}

+

+	/*

+	 * (non-Javadoc)

+	 * 

+	 * @see org.eclipse.wst.xml.core.internal.contentmodel.modelqueryimpl.

+	 * ModelQueryImpl#getCorrespondingCMDocument(org.w3c.dom.Node)

+	 */

+	public CMDocument getCorrespondingCMDocument(Node node) {

+		CMDocument document = super.getCorrespondingCMDocument(node);

+		if (document == null) {

+			ModelQuery embeddedModelQuery = getEmbeddedModelQuery(node);

+			if (embeddedModelQuery != null) {

+				return embeddedModelQuery.getCorrespondingCMDocument(node);

+			}

+		}

+		return document;

+	}

+

+	private String getEmbeddedMimeType(Node node) {

+		String type = DEFAULT_MIMETYPE;

+		if (node instanceof IDOMNode) {

+			IStructuredModel model = ((IDOMNode) node).getModel();

+			String baseLocation = model.getBaseLocation();

+			if (!baseLocation.equals(IModelManager.UNMANAGED_MODEL)) {

+				IPath path = new Path(baseLocation);

+				if (path.segmentCount() > 1) {

+					String key = createPreferenceKey(path);

+					IEclipsePreferences preferences = new ProjectScope(ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0))).getNode(JSPCorePlugin.getDefault().getBundle().getSymbolicName());

+					type = preferences.get(key, DEFAULT_MIMETYPE);

+				}

+			}

+		}

+		return type;

+	}

+

+	private ModelQuery getEmbeddedModelQuery(Node node) {

+		if (fEmbeddedModelQuery == null) {

+			String embeddedMimeType = getEmbeddedMimeType(node);

+			if (embeddedMimeType != null) {

+				EmbeddedTypeHandler embeddedContentTypeHandler = ModelHandlerUtility.getEmbeddedContentTypeFor(embeddedMimeType);

+				if (embeddedContentTypeHandler != null) {

+					List adapterFactories = embeddedContentTypeHandler.getAdapterFactories();

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

+						INodeAdapterFactory factory = (INodeAdapterFactory) adapterFactories.get(i);

+						if (factory.isFactoryForType(ModelQueryAdapter.class)) {

+							INodeAdapter adapter = factory.adapt((INodeNotifier) node.getOwnerDocument());

+							if (adapter instanceof ModelQueryAdapter) {

+								fEmbeddedModelQuery = ((ModelQueryAdapter) adapter).getModelQuery();

+							}

+						}

+					}

+				}

+			}

+		}

+		return fEmbeddedModelQuery;

+	}

+}

diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TagModelQueryCMProvider.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TagModelQueryCMProvider.java
index a411467..8620e8a 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TagModelQueryCMProvider.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/modelquery/TagModelQueryCMProvider.java
@@ -62,7 +62,7 @@
 				if (tldmgr != null) {
 					List documents = tldmgr.getCMDocumentTrackers(node.getPrefix(), xmlNode.getStartOffset());
 					// there shouldn't be more than one cmdocument returned
-					if (documents != null && documents.size() > 0)
+					if (documents != null && !documents.isEmpty())
 						result = (CMDocument) documents.get(0);
 				}
 			}
@@ -70,9 +70,10 @@
 		catch (Exception e) {
 			e.printStackTrace();
 		}
-		if (result == null) {
-			result = tagdoc;
-		}
+// 204990 - JSP/Web Page Editors: tag files do not support content assist on html element attributes
+//		if (result == null) {
+//			result = tagdoc;
+//		}
 		return result;
 	}
 }
diff --git a/bundles/org.eclipse.jst.jsp.ui/plugin.properties b/bundles/org.eclipse.jst.jsp.ui/plugin.properties
index 6628760..7391fb2 100644
--- a/bundles/org.eclipse.jst.jsp.ui/plugin.properties
+++ b/bundles/org.eclipse.jst.jsp.ui/plugin.properties
@@ -41,6 +41,7 @@
 jsp_taglib_directive_uri=URI to the containing JAR file or taglib descriptor (.tld)
 jsp_taglib_directive_prefix=Namespace prefix for tags from this library
 JSPFragmentContentSettings.name=JSP Fragment
+JSP_Property_tag_contentSettings=Tag Content
 command.jsp.refactor.rename.name=Rename
 command.jsp.refactor.rename.description=Rename a Java Element
 command.jsp.refactor.move.name=Move
diff --git a/bundles/org.eclipse.jst.jsp.ui/plugin.xml b/bundles/org.eclipse.jst.jsp.ui/plugin.xml
index a96154b..a2ee28c 100644
--- a/bundles/org.eclipse.jst.jsp.ui/plugin.xml
+++ b/bundles/org.eclipse.jst.jsp.ui/plugin.xml
@@ -907,6 +907,24 @@
 			</enabledWhen>
 			<keywordReference id="org.eclipse.jst.jsp.ui.severities"/>
 		</page>
+		<page
+			name="%JSP_Property_tag_contentSettings"
+			class="org.eclipse.jst.jsp.ui.internal.contentproperties.ui.TagContentSettingsPropertyPage"
+			id="org.eclipse.jst.jsp.ui.propertyPage.project.tag.content.settings"
+			category="org.eclipse.ui.propertypages.info.file">
+         	<enabledWhen>
+               	<and>
+					<adapt type="org.eclipse.core.resources.IFile">
+						<or> 
+							<test 
+								forcePluginActivation="true"
+								property="org.eclipse.core.resources.contentTypeId"
+								value="org.eclipse.jst.jsp.core.tagsource" />
+						</or>
+					</adapt>
+				</and> 
+			</enabledWhen>
+		</page>
 	</extension>	
 	<!--  jsp-for-css editor configurations -->		
 	<extension point="org.eclipse.wst.sse.ui.editorConfiguration">
diff --git a/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/JSPUIMessages.java b/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/JSPUIMessages.java
index 27aa8ae..1731278 100644
--- a/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/JSPUIMessages.java
+++ b/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/JSPUIMessages.java
@@ -116,6 +116,7 @@
 	public static String JSPFContentSettingsPropertyPage_3;
 	public static String JSPFContentSettingsPropertyPage_4;
 	public static String ProjectJSPFContentSettingsPropertyPage_0;
+	public static String TagPropertyPage_desc;
 	public static String Title_InvalidValue;
 	public static String Message_InvalidValue;
 	public static String SyntaxColoringPage_0;
diff --git a/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/JSPUIPluginResources.properties b/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/JSPUIPluginResources.properties
index 7d4313c..197e396 100644
--- a/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/JSPUIPluginResources.properties
+++ b/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/JSPUIPluginResources.properties
@@ -160,3 +160,4 @@
 TLDHyperlink_hyperlinkText=Open Descriptor
 CustomTagHyperlink_hyperlinkText=Open Declaration
 TLDContentOutlineConfiguration_0=Show Content Values
+TagPropertyPage_desc=Specify the surrounding language used in this tag file:
diff --git a/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/contentproperties/ui/TagContentSettingsPropertyPage.java b/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/contentproperties/ui/TagContentSettingsPropertyPage.java
new file mode 100644
index 0000000..b637ba2
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.ui/src/org/eclipse/jst/jsp/ui/internal/contentproperties/ui/TagContentSettingsPropertyPage.java
@@ -0,0 +1,68 @@
+package org.eclipse.jst.jsp.ui.internal.contentproperties.ui;

+

+import org.eclipse.core.resources.IFile;

+import org.eclipse.core.resources.IResource;

+import org.eclipse.core.resources.ProjectScope;

+import org.eclipse.core.runtime.preferences.DefaultScope;

+import org.eclipse.jface.layout.GridDataFactory;

+import org.eclipse.jface.preference.ComboFieldEditor;

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

+import org.eclipse.jst.jsp.core.internal.modelquery.TagModelQuery;

+import org.eclipse.jst.jsp.ui.internal.JSPUIMessages;

+import org.eclipse.swt.SWT;

+import org.eclipse.swt.layout.GridLayout;

+import org.eclipse.swt.widgets.Composite;

+import org.eclipse.swt.widgets.Control;

+import org.eclipse.ui.IWorkbenchPropertyPage;

+import org.eclipse.ui.dialogs.PropertyPage;

+import org.eclipse.ui.preferences.ScopedPreferenceStore;

+

+public class TagContentSettingsPropertyPage extends PropertyPage implements IWorkbenchPropertyPage {

+	private static final String[] fDisplayTypes = {"HTML", "XML"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

+	private static final String[] fValues = {"text/html", "text/xml"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

+	private ComboFieldEditor fComboFieldEditor;

+

+	public TagContentSettingsPropertyPage() {

+		super();

+		noDefaultAndApplyButton();

+		setDescription(JSPUIMessages.TagPropertyPage_desc);

+	}

+

+	protected Control createContents(Composite parent) {

+		Composite composite = new Composite(parent, SWT.NONE);

+		composite.setLayoutData(GridDataFactory.fillDefaults());

+		composite.setLayout(new GridLayout(2, true));

+

+		Object adapter = getElement().getAdapter(IFile.class);

+		if (adapter == null) {

+			adapter = getElement().getAdapter(IResource.class);

+		}

+		if (adapter != null && adapter instanceof IResource) {

+			String preferenceKey = TagModelQuery.createPreferenceKey(((IResource) adapter).getFullPath());

+			new DefaultScope().getNode(JSPCorePlugin.getDefault().getBundle().getSymbolicName()).put(preferenceKey, fValues[0]);

+			ScopedPreferenceStore store = new ScopedPreferenceStore(new ProjectScope(((IResource) adapter).getProject()), JSPCorePlugin.getDefault().getBundle().getSymbolicName());

+

+			String[][] entryNamesAndValues = new String[][]{{fDisplayTypes[0], fValues[0]}, {fDisplayTypes[1], fValues[1]}};

+			fComboFieldEditor = new ComboFieldEditor(preferenceKey, JSPUIMessages.JSPFContentSettingsPropertyPage_2, entryNamesAndValues, composite);

+			fComboFieldEditor.fillIntoGrid(composite, 2);

+			fComboFieldEditor.setPreferenceStore(store);

+			fComboFieldEditor.load();

+

+			// let the page save for us if needed

+			setPreferenceStore(store);

+		}

+		return composite;

+	}

+

+	/*

+	 * (non-Javadoc)

+	 * 

+	 * @see org.eclipse.jface.preference.PreferencePage#performOk()

+	 */

+	public boolean performOk() {

+		if (fComboFieldEditor != null) {

+			fComboFieldEditor.store();

+		}

+		return super.performOk();

+	}

+}