/******************************************************************************* * Copyright (c) 2006 Sybase, Inc. 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: * Sybase, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.jst.pagedesigner.utils; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.core.runtime.content.IContentTypeManager; import org.eclipse.jst.jsf.common.metadata.Model; import org.eclipse.jst.jsf.common.metadata.Trait; import org.eclipse.jst.jsf.common.metadata.internal.IMetaDataDomainContext; import org.eclipse.jst.jsf.common.metadata.internal.TraitValueHelper; import org.eclipse.jst.jsf.common.metadata.query.internal.MetaDataQueryContextFactory; import org.eclipse.jst.jsf.common.metadata.query.internal.MetaDataQueryFactory; import org.eclipse.jst.jsf.common.metadata.query.internal.taglib.ITaglibDomainMetaDataQuery; import org.eclipse.jst.jsf.context.resolver.structureddocument.IStructuredDocumentContextResolverFactory; import org.eclipse.jst.jsf.context.resolver.structureddocument.IWorkspaceContextResolver; import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContext; import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContextFactory; import org.eclipse.jst.jsf.core.internal.tld.ITLDConstants; 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.TLDDocument; import org.eclipse.jst.jsp.core.taglib.TaglibIndex; import org.eclipse.jst.pagedesigner.css2.property.ICSSPropertyID; import org.eclipse.jst.pagedesigner.dom.EditModelQuery; import org.eclipse.jst.pagedesigner.jsp.core.IJSPCoreConstants; import org.eclipse.wst.html.core.internal.format.HTMLFormatProcessorImpl; import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; 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; /** * utility class for JSP related information. * * @author mengbo */ public class JSPUtil { /** * JSP source contenttype */ public static final IContentType JSP_CONTENTTYPE = Platform.getContentTypeManager().getContentType("org.eclipse.jst.jsp.core.jspsource"); //$NON-NLS-1$ /** * find out whether the specified taglib has been defined in the IDOMModel. * If found, then return the prefix. If can't find, then will try to add a * taglib declaration into the model, and try to use the specified default * prefix * * @param model * @param uri * @param defaultPrefix * @return prefix */ public static String getOrCreatePrefix(IDOMModel model, String uri, String defaultPrefix) { return getOrCreatePrefix(model, uri, defaultPrefix, null); } /** * * @param model * @param uri * @param defaultPrefix * @param nodes * if a taglib node is created, then the created tag lib node is * returned in this. In the case of xml format, it is the attribute node on * jsp:root * @return prefix */ public static String getOrCreatePrefix(IDOMModel model, String uri, String defaultPrefix, Node[] nodes) { String prefix = getPrefix(model, uri); if (prefix != null) { return prefix; } prefix = findUnusedPrefix(model, defaultPrefix); //need proper API to determine xml type... this may need to change in future if (! model.getDocument().isXMLType()){ // TODO: should create the taglib inside the IDOMModel //this is virtually the same as createTaglibDeclaration... fix me Node[] ref = new Node[1]; BodyHelper.findHeaderInsertPosition(ITLDConstants.URI_JSP, "taglib", //$NON-NLS-1$ model.getDocument(), ref); Element ele = model.getDocument().createElement("jsp:directive.taglib"); //$NON-NLS-1$ ((IDOMElement) ele).setJSPTag(true); if (isTagDir(uri, model)) { ele.setAttribute(IJSPCoreConstants.ATTR_TAGDIR, uri); } else { ele.setAttribute(IJSPCoreConstants.ATTR_URI, uri); } ele.setAttribute(ICSSPropertyID.ATTR_PREFIX, prefix); if (nodes != null && nodes.length > 0) { nodes[0] = ele; } model.getDocument().insertBefore(ele, ref[0]); new HTMLFormatProcessorImpl().formatNode(ele); } else {//xml format //find root element boolean tldRefExists = false; Element root = getRootElement(model); if (root != null){ NamedNodeMap attrs = root.getAttributes(); for (int i=0;i<attrs.getLength();i++){ Attr a = (Attr)attrs.item(i); //is the taglib uri already declared? if (a.getValue().equals(uri)){ tldRefExists = true; break; } } if (!tldRefExists){ //create attribute Attr a = model.getDocument().createAttribute("xmlns:"+prefix); //$NON-NLS-1$ a.setValue(uri); root.setAttributeNode(a); new HTMLFormatProcessorImpl().formatNode(root); //duplicating what non-xml case does... no callerd making use of this currently if (nodes != null && nodes.length > 0) { nodes[0] = a; } } } } return prefix; } private static boolean isTagDir(final String uri, final IDOMModel model) { final IStructuredDocumentContext context = IStructuredDocumentContextFactory.INSTANCE.getContext(model.getStructuredDocument(), 0); if (context != null) { IFile file = StructuredModelUtil.getFileFor(model); // IWorkspaceContextResolver resolver = IStructuredDocumentContextResolverFactory.INSTANCE.getWorkspaceContextResolver(context); // if (resolver != null) { if (file != null) { final IMetaDataDomainContext mdcontext = MetaDataQueryContextFactory.getInstance().createTaglibDomainModelContext(file); final ITaglibDomainMetaDataQuery query = MetaDataQueryFactory.getInstance().createQuery(mdcontext); final Model m = query.findTagLibraryModel(uri); final Trait t = query.findTrait(m, "isTagDir"); //$NON-NLS-1$ return TraitValueHelper.getValueAsBoolean(t); } } return false; } private static Element getRootElement(IDOMModel model) { Document docNode = EditModelQuery.getDocumentNode(model.getDocument()); return docNode.getDocumentElement(); } /** * Return prefix for taglib if declared in jsp file * @param model * @param uri * @return null means this is tld is not declared in the jsp file */ public static String getPrefix(IDOMModel model, String uri) { TLDCMDocumentManager m = TaglibController.getTLDCMDocumentManager(model .getStructuredDocument()); if (m == null) { // if the doc manager has nothing but the type is XML, // then see if the prefix is encoded as a namespace in // the doc root if (model.getDocument().isXMLType()) { Element root = getRootElement(model); if (root != null){ NamedNodeMap attrs = root.getAttributes(); for (int i=0;i<attrs.getLength();i++){ Attr a = (Attr)attrs.item(i); //is the taglib uri already declared? if (a.getValue().equals(uri) && a.getName().startsWith("xmlns:")) //$NON-NLS-1$ { String prefix = a.getNodeName().substring("xmlns:".length()); //$NON-NLS-1$ if ("".equals(prefix)) //$NON-NLS-1$ { prefix = null; } return prefix; } } } } return null; } List trackers = m.getTaglibTrackers(); for (Iterator iter = trackers.iterator(); iter.hasNext();) { TaglibTracker tracker = (TaglibTracker) iter.next(); if (uri.equals(tracker.getURI())) { return tracker.getPrefix(); } CMDocument cmdoc = tracker.getDocument(); if (cmdoc instanceof TLDDocument && uri.equals(((TLDDocument) cmdoc).getUri())) { return tracker.getPrefix(); } } return null; } /** * create specified taglib declaration as jsp directive element * * @param model * @param uri * @param prefix * @return Element */ public static Element createTaglibDeclaration(IDOMModel model, String uri, String prefix) { //seemingly unused - 5/6/09 Node[] ref = new Node[1]; BodyHelper.findHeaderInsertPosition(ITLDConstants.URI_JSP, "taglib", //$NON-NLS-1$ model.getDocument(), ref); Element ele = model.getDocument().createElement("jsp:directive.taglib"); //$NON-NLS-1$ ((IDOMElement) ele).setJSPTag(true); if (isTagDir(uri, model)) { ele.setAttribute(IJSPCoreConstants.ATTR_TAGDIR, uri); } else { ele.setAttribute(IJSPCoreConstants.ATTR_URI, uri); } ele.setAttribute("prefix", prefix); //$NON-NLS-1$ model.getDocument().insertBefore(ele, ref[0]); return ele; } /** * Return prefix to use based upon the suggestion. * Appends an integer until unique, if suggestion was used. * @param model * @param suggestion * @return prefix */ public static String findUnusedPrefix(IDOMModel model, String suggestion) { if (suggestion == null) { suggestion = "p"; //$NON-NLS-1$ } TLDCMDocumentManager m = TaglibController.getTLDCMDocumentManager(model .getStructuredDocument()); if (m == null) { return suggestion; } List trackers = m.getTaglibTrackers(); Set map = new HashSet(); for (Iterator iter = trackers.iterator(); iter.hasNext();) { TaglibTracker tracker = (TaglibTracker) iter.next(); map.add(tracker.getPrefix()); } if (!map.contains(suggestion)) { return suggestion; } for (int i = 1;; i++) { if (!map.contains(suggestion + i)) { return suggestion + i; } } } /** * given the prefix, find the corresponding jsp tld URI. * * @param model * @param prefix * @return prefix */ public static String findURIForPrefix(IDOMModel model, String prefix) { if (prefix == null || model == null) { return null; } TLDCMDocumentManager m = TaglibController.getTLDCMDocumentManager(model .getStructuredDocument()); if (m == null) { return null; } List trackers = m.getTaglibTrackers(); for (Iterator iter = trackers.iterator(); iter.hasNext();) { TaglibTracker tracker = (TaglibTracker) iter.next(); if (prefix.equals(tracker.getPrefix())) { CMDocument cmdoc = tracker.getDocument(); if (cmdoc instanceof TLDDocument) { return ((TLDDocument) cmdoc).getUri(); } break; // fall out and return null } } return null; } /** * judge whether the the baseFile belonged project can support uri specified * tag lib * * @param uri * tag lib uri * @param baseFile * @return boolean */ public static boolean supportTaglib(String uri, IFile baseFile) { //IPath location = baseFile.getLocation(); //Bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=221197 IPath location = baseFile.getFullPath(); if (location != null) { return TaglibIndex.resolve(location.toString(), uri, false) != null; } return false; } /** * @param model * @return true if model is a JSP contenttype */ public static boolean isJSPModel(IDOMModel model) { final IContentTypeManager typeManager = Platform.getContentTypeManager(); final IStructuredDocumentContext context = IStructuredDocumentContextFactory.INSTANCE.getContext(model.getStructuredDocument(), 0); final IWorkspaceContextResolver resolver = IStructuredDocumentContextResolverFactory.INSTANCE.getWorkspaceContextResolver(context); final IFile file = (IFile)resolver.getResource(); final IContentType contentType = typeManager.findContentTypeFor(file.getName()); return contentType.isKindOf(JSP_CONTENTTYPE); } }