Package org.eclipse.jst.jsp.core.internal.taglib

Source Code of org.eclipse.jst.jsp.core.internal.taglib.TaglibHelper

/*******************************************************************************
* 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.jst.jsp.core.internal.taglib;


import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.jsp.tagext.FunctionInfo;
import javax.servlet.jsp.tagext.TagAttributeInfo;
import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagExtraInfo;
import javax.servlet.jsp.tagext.TagFileInfo;
import javax.servlet.jsp.tagext.TagInfo;
import javax.servlet.jsp.tagext.TagLibraryInfo;
import javax.servlet.jsp.tagext.ValidationMessage;
import javax.servlet.jsp.tagext.VariableInfo;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
import org.eclipse.jst.jsp.core.internal.Logger;
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.contentmodel.tld.provisional.TLDDocument;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDElementDeclaration;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDVariable;
import org.eclipse.jst.jsp.core.internal.java.IJSPProblem;
import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.NotImplementedException;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
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.ITextRegionList;
import org.eclipse.wst.sse.core.internal.util.AbstractMemoryListener;
import org.eclipse.wst.sse.core.utils.StringUtils;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMNodeWrapper;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.osgi.service.event.Event;

import com.ibm.icu.text.MessageFormat;

/**
* This class helps find TaglibVariables in a JSP file.
*/
public class TaglibHelper {

  private static final String ITERATION_QUALIFIER = "javax.servlet.jsp.tagext"; //$NON-NLS-1$
  private static final String ITERATION_NAME = "IterationTag"; //$NON-NLS-1$
 
  // for debugging
  private static final boolean DEBUG;
  static {
    String value = Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/taglibvars"); //$NON-NLS-1$
    DEBUG = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
  }

  private IProject fProject = null;
  private ClassLoader fLoader = 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
   */
  private Set fNotFoundClasses = null;

  private Map fClassMap = null;

  /**
   * Used to keep the {@link #fNotFoundClasses} cache clean when memory is low
   */
  private MemoryListener fMemoryListener;

  public TaglibHelper(IProject project) {
    super();
    setProject(project);
    fMemoryListener = new MemoryListener();
    fMemoryListener.connect();
    fNotFoundClasses = new HashSet();
    fClassMap = Collections.synchronizedMap(new HashMap());
  }

  /**
   * Checks that <code>type</code> implements an IterationTag
   *
   * @param type
   * @return true if <code>type</code> implements IterationTag
   * @throws JavaModelException
   * @throws ClassNotFoundException thrown when the <code>type</code> is null
   */
  private boolean isIterationTag(IType type) throws JavaModelException, ClassNotFoundException {
    if (type == null) {
      throw new ClassNotFoundException();
    }
    synchronized (fClassMap) {
      if (fClassMap.containsKey(type.getFullyQualifiedName()))
        return ((Boolean) fClassMap.get(type.getFullyQualifiedName())).booleanValue();
    }

    String signature;
    String qualifier;
    String name;
    String[] interfaces = type.getSuperInterfaceTypeSignatures();
    boolean isIteration = false;
    // Check any super interfaces for the iteration tag
    for (int i = 0; i < interfaces.length; i++) {
      // For source files, the interface may need to be resolved
      String erasureSig = Signature.getTypeErasure(interfaces[i]);
      qualifier = Signature.getSignatureQualifier(erasureSig);
      name = Signature.getSignatureSimpleName(erasureSig);
      // Interface type is unresolved
      if (erasureSig.charAt(0) == Signature.C_UNRESOLVED) {
        String[][] types = type.resolveType(getQualifiedType(qualifier, name));
        // Type was resolved
        if (types != null && types.length > 0) {
          isIteration = handleInterface(type, types[0][0], types[0][1]);
        }
      }
      else {
        isIteration = handleInterface(type, qualifier, name);
      }
      if (isIteration)
        return true;
    }

    signature = type.getSuperclassTypeSignature();
    if (signature != null) {
      String erasureSig = Signature.getTypeErasure(signature);
      qualifier = Signature.getSignatureQualifier(erasureSig);
      name = Signature.getSignatureSimpleName(erasureSig);
      // superclass was unresolved
      if (erasureSig.charAt(0) == Signature.C_UNRESOLVED) {
        String[][] types = type.resolveType(getQualifiedType(qualifier, name));
        // Type was resolved
        if (types != null && types.length > 0) {
          isIteration = isIterationTag(fJavaProject.findType(types[0][0], types[0][1]));
        }
      }
      else {
        isIteration = isIterationTag(fJavaProject.findType(qualifier, name));
      }
    }
    fClassMap.put(type.getFullyQualifiedName(), Boolean.valueOf(isIteration));
    return isIteration;
  }

  private boolean handleInterface(IType type, String qualifier, String name) throws JavaModelException, ClassNotFoundException {
    boolean isIteration = false;
    // Qualified interface is an iteration tag
    if (ITERATION_QUALIFIER.equals(qualifier) && ITERATION_NAME.equals(name))
      isIteration = true;
    // Check ancestors of this interface
    else
      isIteration = isIterationTag(fJavaProject.findType(qualifier, name));

    fClassMap.put(type.getFullyQualifiedName(), Boolean.valueOf(isIteration));
    return isIteration;
  }

  private String getQualifiedType(String qualifier, String name) {
    StringBuffer qual = new StringBuffer(qualifier);
    if (qual.length() > 0)
      qual.append('.');
    qual.append(name);
    return qual.toString();
  }

  private boolean isIterationTag(TLDElementDeclaration elementDecl, IStructuredDocument document, ITextRegionCollection customTag, List problems) {
    String className = elementDecl.getTagclass();
    if (className == null || className.length() == 0 || fProject == null || fNotFoundClasses.contains(className))
      return false;

    try {
      synchronized (fClassMap) {
        if (fClassMap.containsKey(className))
          return ((Boolean) fClassMap.get(className)).booleanValue();
      }
      return isIterationTag(fJavaProject.findType(className));
    } 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);
      if (DEBUG)
        Logger.logException(className, e);
    } catch (JavaModelException e) {
      if (DEBUG)
        Logger.logException(className, e);
    } catch (Exception e) {
      // this is 3rd party code, need to catch all errors
      if (DEBUG)
        Logger.logException(className, e);
    } catch (Error e) {
      // this is 3rd party code, need to catch all errors
      if (DEBUG)
        Logger.logException(className, e);
    }

    return false;
  }

  public CustomTag getCustomTag(String tagToAdd, IStructuredDocument structuredDoc, ITextRegionCollection customTag, List problems) {
    List results = new ArrayList();
    boolean isIterationTag = false;
    String tagClass = null;
    String teiClass = null;
    if (problems == null)
      problems = new ArrayList();
    ModelQuery mq = getModelQuery(structuredDoc);
    if (mq != null) {
      TLDCMDocumentManager mgr = TaglibController.getTLDCMDocumentManager(structuredDoc);

      if (mgr != null) {

        List trackers = mgr.getCMDocumentTrackers(-1);
        Iterator taglibs = trackers.iterator();
 
        CMDocument doc = null;
        CMNamedNodeMap elements = null;
        while (taglibs.hasNext()) {
          doc = (CMDocument) taglibs.next();
          CMNode node = null;
          if ((elements = doc.getElements()) != null && (node = elements.getNamedItem(tagToAdd)) != null && node.getNodeType() == CMNode.ELEMENT_DECLARATION) {
 
            if (node instanceof CMNodeWrapper) {
              node = ((CMNodeWrapper) node).getOriginNode();
            }
            TLDElementDeclaration tldElementDecl = (TLDElementDeclaration) node;

            tagClass = tldElementDecl.getTagclass();
            teiClass = tldElementDecl.getTeiclass();
            isIterationTag = isIterationTag(tldElementDecl, structuredDoc, customTag, problems);
            /*
             * Although clearly not the right place to add validation
             * design-wise, this is the first time we have the
             * necessary information to validate the tag class.
             */
            validateTagClass(structuredDoc, customTag, tldElementDecl, problems);
 
            // 1.2+ taglib style
            addVariables(results, node, customTag);
 
            // for 1.1 need more info from taglib tracker
            if (doc instanceof TaglibTracker) {
              String uri = ((TaglibTracker) doc).getURI();
              String prefix = ((TaglibTracker) doc).getPrefix();
              // only for 1.1 taglibs
              addTEIVariables(structuredDoc, customTag, results, tldElementDecl, prefix, uri, problems);
            }
            break;
          }
        }
      }
    }

    return new CustomTag(tagToAdd, tagClass, teiClass, (TaglibVariable[]) results.toArray(new TaglibVariable[results.size()]), isIterationTag);
  }
  /**
   * @param tagToAdd
   *            is the name of the tag whose variables we want
   * @param structuredDoc
   *            is the IStructuredDocument where the tag is found
   * @param customTag
   *            is the IStructuredDocumentRegion opening tag for the custom
   *            tag
   * @param problems problems that are generated while creating variables are added to this collection
   */
  public TaglibVariable[] getTaglibVariables(String tagToAdd, IStructuredDocument structuredDoc, ITextRegionCollection customTag, List problems) {

    List results = new ArrayList();
    if (problems == null)
      problems = new ArrayList();
    ModelQuery mq = getModelQuery(structuredDoc);
    if (mq != null) {
      TLDCMDocumentManager mgr = TaglibController.getTLDCMDocumentManager(structuredDoc);

      // TaglibSupport support = ((TaglibModelQuery)
      // mq).getTaglibSupport();
      if (mgr == null)
        return new TaglibVariable[0];

      List trackers = mgr.getCMDocumentTrackers(-1);
      Iterator taglibs = trackers.iterator();

      // TaglibSupport support = ((TaglibModelQuery)
      // mq).getTaglibSupport();
      // if (support == null)
      // return new TaglibVariable[0];
      //
      // Iterator taglibs =
      // support.getCMDocuments(customTag.getStartOffset()).iterator();
      CMDocument doc = null;
      CMNamedNodeMap elements = null;
      while (taglibs.hasNext()) {
        doc = (CMDocument) taglibs.next();
        CMNode node = null;
        if ((elements = doc.getElements()) != null && (node = elements.getNamedItem(tagToAdd)) != null && node.getNodeType() == CMNode.ELEMENT_DECLARATION) {

          if (node instanceof CMNodeWrapper) {
            node = ((CMNodeWrapper) node).getOriginNode();
          }
          TLDElementDeclaration tldElementDecl = (TLDElementDeclaration) node;

          /*
           * Although clearly not the right place to add validation
           * design-wise, this is the first time we have the
           * necessary information to validate the tag class.
           */
          validateTagClass(structuredDoc, customTag, tldElementDecl, problems);

          // 1.2+ taglib style
          addVariables(results, node, customTag);

          // for 1.1 need more info from taglib tracker
          if (doc instanceof TaglibTracker) {
            String uri = ((TaglibTracker) doc).getURI();
            String prefix = ((TaglibTracker) doc).getPrefix();
            // only for 1.1 taglibs
            addTEIVariables(structuredDoc, customTag, results, tldElementDecl, prefix, uri, problems);
          }
        }
      }
    }

    return (TaglibVariable[]) results.toArray(new TaglibVariable[results.size()]);
  }

  /**
   * Adds 1.2 style TaglibVariables to the results list.
   *
   * @param results
   *            list where the <code>TaglibVariable</code> s are added
   * @param node
   */
  private void addVariables(List results, CMNode node, ITextRegionCollection customTag) {
    List list = ((TLDElementDeclaration) node).getVariables();
    Iterator it = list.iterator();
    while (it.hasNext()) {
      TLDVariable var = (TLDVariable) it.next();
      if (!var.getDeclare())
        continue;

      String varName = var.getNameGiven();
      if (varName == null) {
        // 2.0
        varName = var.getAlias();
      }
      if (varName == null) {
        String attrName = var.getNameFromAttribute();
        /*
         * Iterate through the document region to find the
         * corresponding attribute name, and then use its value
         */
        ITextRegionList regions = customTag.getRegions();
        boolean attrNameFound = false;
        for (int i = 2; i < regions.size(); i++) {
          ITextRegion region = regions.get(i);
          if (DOMRegionContext.XML_TAG_ATTRIBUTE_NAME.equals(region.getType())) {
            attrNameFound = attrName.equals(customTag.getText(region));
          }
          if (attrNameFound && DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE.equals(region.getType())) {
            varName = StringUtils.strip(customTag.getText(region));
          }
        }
      }
      if (varName != null) {
        String varClass = "java.lang.String"; // the default
        // class...//$NON-NLS-1$
        if (var.getVariableClass() != null) {
          varClass = var.getVariableClass();
        }
        results.add(new TaglibVariable(varClass, varName, var.getScope(), var.getDescription()));
      }
    }
  }

  /**
   * Adds 1.1 style TaglibVariables (defined in a TagExtraInfo class) to the
   * results list. Also reports problems with the tag and tei classes in
   * fTranslatorProblems.
   *
   * @param customTag
   * @param results
   *            list where the <code>TaglibVariable</code> s are added
   * @param decl
   *            TLDElementDeclaration for the custom tag
   * @param prefix
   *            custom tag prefix
   * @param uri
   *            URI where the tld can be found
   */
  private void addTEIVariables(IStructuredDocument document, ITextRegionCollection customTag, List results, TLDElementDeclaration decl, String prefix, String uri, List problems) {
    String teiClassname = decl.getTeiclass();
    if (teiClassname == null || teiClassname.length() == 0 || fJavaProject == null || fNotFoundClasses.contains(teiClassname))
      return;

    ClassLoader loader = getClassloader();

    Class teiClass = null;
    try {
      /*
       * 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)) {
          TagExtraInfo tei = (TagExtraInfo) teiObject;
          Hashtable tagDataTable = extractTagData(customTag);
          TagInfo info = getTagInfo(decl, tei, prefix, uri);
          if (info != null) {
            tei.setTagInfo(info);

            // add to results
            TagData td = new TagData(tagDataTable);

            VariableInfo[] vInfos = tei.getVariableInfo(td);
            if (vInfos != null) {
              for (int i = 0; i < vInfos.length; i++) {
                results.add(new TaglibVariable(vInfos[i].getClassName(), vInfos[i].getVarName(), vInfos[i].getScope(), decl.getDescription()));
              }
            }

            ValidationMessage[] messages = tei.validate(td);
            if (messages != null && messages.length > 0) {
              for (int i = 0; i < messages.length; i++) {
                Object createdProblem = createValidationMessageProblem(document, customTag, messages[i].getMessage());
                if (createdProblem != null) {
                  problems.add(createdProblem);
                }
              }
            }
          }
        }
        else {
          Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TEIClassMisc, JSPCoreMessages.TaglibHelper_2, teiClassname, true);
          if (createdProblem != null) {
            problems.add(createdProblem);
          }
          // this is 3rd party code, need to catch all exceptions
          if (DEBUG) {
            Logger.log(Logger.WARNING, teiClassname + " is not a subclass of TaxExtraInfo"); //$NON-NLS-1$
          }
        }
      }
    }
    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);
      }
      // TEI class wasn't on build path
      if (DEBUG)
        logException(teiClassname, e);
    }
    catch (InstantiationException e) {
      Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TEIClassNotInstantiated, JSPCoreMessages.TaglibHelper_1, teiClassname, true);
      if (createdProblem != null) {
        problems.add(createdProblem);
      }
      // TEI class couldn't be instantiated
      if (DEBUG)
        logException(teiClassname, e);
    }
    catch (IllegalAccessException e) {
      if (DEBUG)
        logException(teiClassname, e);
    }
    // catch (ClassCastException e) {
    // // TEI class wasn't really a subclass of TagExtraInfo
    // if (DEBUG)
    // logException(teiClassname, e);
    // }
    catch (Exception e) {
      Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TEIClassMisc, JSPCoreMessages.TaglibHelper_2, teiClassname, true);
      if (createdProblem != null) {
        problems.add(createdProblem);
      }
      // this is 3rd party code, need to catch all exceptions
      if (DEBUG)
        logException(teiClassname, e);
    }
    catch (Error e) {
      // this is 3rd party code, need to catch all errors
      Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TEIClassNotInstantiated, JSPCoreMessages.TaglibHelper_1, teiClassname, true);
      if (createdProblem != null) {
        problems.add(createdProblem);
      }
      if (DEBUG)
        logException(teiClassname, e);
    }
    finally {
      // Thread.currentThread().setContextClassLoader(oldLoader);
    }
  }

  /**
   * @param customTag
   * @param teiClass
   * @return
   */
  private Object createJSPProblem(final IStructuredDocument document, final ITextRegionCollection customTag, final int problemID, final String messageKey, final String argument, boolean preferVars) {
    final String tagname = customTag.getText(customTag.getRegions().get(1));

    final int start;
    if (customTag.getNumberOfRegions() > 1) {
      start = customTag.getStartOffset(customTag.getRegions().get(1));
    }
    else {
      start = customTag.getStartOffset();
    }

    final int end;
    if (customTag.getNumberOfRegions() > 1) {
      end = customTag.getTextEndOffset(customTag.getRegions().get(1)) - 1;
    }
    else {
      end = customTag.getTextEndOffset() - 1;
    }

    final int line = document.getLineOfOffset(start);

    final char[] name;
    IPath location = TaglibController.getLocation(document);
    if (location == null) {
      name = new char[0];
    }
    else {
      name = location.toString().toCharArray();
    }

    /*
     * Note: these problems would result in translation errors on the
     * server, so the severity is not meant to be controllable
     */
    return new IJSPProblem() {
      public void setSourceStart(int sourceStart) {
      }

      public void setSourceLineNumber(int lineNumber) {
      }

      public void setSourceEnd(int sourceEnd) {
      }

      public boolean isWarning() {
        return false;
      }

      public boolean isError() {
        return true;
      }

      public int getSourceStart() {
        return start;
      }

      public int getSourceLineNumber() {
        return line;
      }

      public int getSourceEnd() {
        return end;
      }

      public char[] getOriginatingFileName() {
        return name;
      }

      public String getMessage() {
        return MessageFormat.format(messageKey, new String[]{tagname, argument});
      }

      public int getID() {
        return problemID;
      }

      public String[] getArguments() {
        return new String[0];
      }

      public int getEID() {
        return problemID;
      }
    };
  }

  /**
   * @param customTag
   * @param validationMessage
   * @return
   */
  private Object createValidationMessageProblem(final IStructuredDocument document, final ITextRegionCollection customTag, final String validationMessage) {
    final int start;
    if (customTag.getNumberOfRegions() > 3) {
      start = customTag.getStartOffset(customTag.getRegions().get(2));
    }
    else if (customTag.getNumberOfRegions() > 1) {
      start = customTag.getStartOffset(customTag.getRegions().get(1));
    }
    else {
      start = customTag.getStartOffset();
    }

    final int end;
    if (customTag.getNumberOfRegions() > 3) {
      end = customTag.getTextEndOffset(customTag.getRegions().get(customTag.getNumberOfRegions() - 2)) - 1;
    }
    else if (customTag.getNumberOfRegions() > 1) {
      end = customTag.getTextEndOffset(customTag.getRegions().get(1)) - 1;
    }
    else {
      end = customTag.getTextEndOffset();
    }

    final int line = document.getLineOfOffset(start);

    final char[] name;
    IPath location = TaglibController.getLocation(document);
    if (location == null) {
      name = new char[0];
    }
    else {
      name = location.toString().toCharArray();
    }

    return new IJSPProblem() {
      public void setSourceStart(int sourceStart) {
      }

      public void setSourceLineNumber(int lineNumber) {
      }

      public void setSourceEnd(int sourceEnd) {
      }

      public boolean isWarning() {
        return true;
      }

      public boolean isError() {
        return false;
      }

      public int getSourceStart() {
        return start;
      }

      public int getSourceLineNumber() {
        return line;
      }

      public int getSourceEnd() {
        return end;
      }

      public char[] getOriginatingFileName() {
        return name;
      }

      public String getMessage() {
        return validationMessage;
      }

      public int getID() {
        return getEID();
      }

      public String[] getArguments() {
        return new String[0];
      }

      public int getEID() {
        return IJSPProblem.TEIValidationMessage;
      }
    };
  }

  /**
   * @param decl
   * @return the TagInfo for the TLDELementDeclaration if the declaration is
   *         valid, otherwise null
   */
  private TagInfo getTagInfo(final TLDElementDeclaration decl, TagExtraInfo tei, String prefix, String uri) {

    TagLibraryInfo libInfo = new TagLibraryInfoImpl(prefix, uri, decl);

    CMNamedNodeMap attrs = decl.getAttributes();
    TagAttributeInfo[] attrInfos = new TagAttributeInfo[attrs.getLength()];
    TLDAttributeDeclaration attr = null;
    String type = ""; //$NON-NLS-1$

    // get tag attribute infos
    for (int i = 0; i < attrs.getLength(); i++) {
      attr = (TLDAttributeDeclaration) attrs.item(i);
      type = attr.getType();
      // default value for type is String
      if (attr.getType() == null || attr.getType().equals("")) //$NON-NLS-1$
        type = "java.lang.String"; //$NON-NLS-1$
      attrInfos[i] = new TagAttributeInfo(attr.getAttrName(), attr.isRequired(), type, false);
    }

    String tagName = decl.getNodeName();
    String tagClass = decl.getTagclass();
    String bodyContent = decl.getBodycontent();
    if (tagName != null && tagClass != null && bodyContent != null)
      return new TagInfo(tagName, tagClass, bodyContent, decl.getInfo(), libInfo, tei, attrInfos);
    return null;

  }

  /**
   * @param e
   */
  private void logException(String teiClassname, Throwable e) {

    String message = "teiClassname: ["; //$NON-NLS-1$
    if (teiClassname != null)
      message += teiClassname;
    message += "]"; //$NON-NLS-1$
    Logger.logException(message, e);
  }

  /**
   * Returns all attribute -> value pairs for the tag in a Hashtable.
   *
   * @param customTag
   * @return
   */
  private Hashtable extractTagData(ITextRegionCollection customTag) {
    Hashtable tagDataTable = new Hashtable();
    ITextRegionList regions = customTag.getRegions();
    ITextRegion r = null;
    String attrName = ""; //$NON-NLS-1$
    String attrValue = ""; //$NON-NLS-1$
    final int size = regions.size();
    for (int i = 2; i < size; i++) {
      r = regions.get(i);
      // check if attr name
      if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
        attrName = customTag.getText(r);
        // check equals is next region
        if (size > ++i) {
          r = regions.get(i);
          if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS && size > ++i) {
            // get attr value
            r = regions.get(i);
            final String type = r.getType();
            if (type == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
              // attributes in our document have quotes, so we
              // need to strip them
              attrValue = StringUtils.stripQuotes(customTag.getText(r));
              tagDataTable.put(attrName, attrValue);
            }
            else if (type == DOMJSPRegionContexts.JSP_TAG_ATTRIBUTE_VALUE_DQUOTE || type == DOMJSPRegionContexts.JSP_TAG_ATTRIBUTE_VALUE_SQUOTE) {
              final StringBuffer buffer = new StringBuffer();
              while (size > ++i && (r = regions.get(i)).getType() != type) {
                buffer.append(customTag.getText(r));
              }
              tagDataTable.put(attrName, buffer.toString());
            }
          }
        }
      }
    }

    tagDataTable.put("jsp:id", customTag.getText(regions.get(1)) + "_" + customTag.getStartOffset()); //$NON-NLS-1$

    return tagDataTable;
  }

  private ClassLoader getClassloader() {
    if (fLoader == null) {
      fLoader = new BuildPathClassLoader(this.getClass().getClassLoader(), fJavaProject);
    }
    return fLoader;
  }

  /**
   * @return Returns the fModelQuery.
   */
  public ModelQuery getModelQuery(IDocument doc) {
    IStructuredModel model = null;
    ModelQuery mq = null;
    try {
      model = StructuredModelManager.getModelManager().getExistingModelForRead(doc);
      mq = ModelQueryUtil.getModelQuery(model);
    }
    finally {
      if (model != null)
        model.releaseFromRead();
    }
    return mq;
  }


  /**
   * @return Returns the fFile.
   */
  public IProject getProject() {

    return fProject;
  }

  /**
   * @param file
   *            The fFile to set.
   */
  public void setProject(IProject p) {
    fProject = p;
    IJavaProject javaProject = JavaCore.create(p);
    if (javaProject.exists()) {
      fJavaProject = javaProject;
    }
  }

  private void validateTagClass(IStructuredDocument document, ITextRegionCollection customTag, TLDElementDeclaration decl, List problems) {
    // skip if from a tag file
    if (TLDElementDeclaration.SOURCE_TAG_FILE.equals(decl.getProperty(TLDElementDeclaration.TAG_SOURCE)) || fJavaProject == null) {
      return;
    }

    String tagClassname = decl.getTagclass();
    Object tagClass = null;
    if (tagClassname != null && tagClassname.length() > 0 && fJavaProject.exists()) {
      try {
        tagClass = fJavaProject.findType(tagClassname);
      }
      catch (JavaModelException e) {
        Logger.logException(e);
      }
    }
    if (tagClass == null) {
      Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TagClassNotFound, JSPCoreMessages.TaglibHelper_3, tagClassname, false);
      if (createdProblem != null) {
        problems.add(createdProblem);
      }
    }
  }

  /**
   *
   */
  public void dispose() {
    fLoader = null;
    fJavaProject = null;
    fProject = null;
    fNotFoundClasses = null;
    fClassMap = null;
    fMemoryListener.disconnect();
    fMemoryListener = null;
  }

  public void invalidateClass(String className) {
    fClassMap.remove(className);
  }

  /**
   * <p>A {@link AbstractMemoryListener} that clears the {@link #fNotFoundClasses} cache
   * whenever specific memory events are received.</p>
   *
   * <p>Events:
   * <ul>
   * <li>{@link AbstractMemoryListener#SEV_NORMAL}</li>
   * <li>{@link AbstractMemoryListener#SEV_SERIOUS}</li>
   * <li>{@link AbstractMemoryListener#SEV_CRITICAL}</li>
   * </ul>
   * </p>
   */
  private class MemoryListener extends AbstractMemoryListener {
    /**
     * <p>Constructor causes this listener to listen for specific memory events.</p>
     * <p>Events:
     * <ul>
     * <li>{@link AbstractMemoryListener#SEV_NORMAL}</li>
     * <li>{@link AbstractMemoryListener#SEV_SERIOUS}</li>
     * <li>{@link AbstractMemoryListener#SEV_CRITICAL}</li>
     * </ul>
     * </p>
     */
    MemoryListener() {
      super(new String[] { SEV_NORMAL, SEV_SERIOUS, SEV_CRITICAL });
    }

    /**
     * On any memory event we handle clear out the project descriptions
     *
     * @see org.eclipse.jst.jsp.core.internal.util.AbstractMemoryListener#handleMemoryEvent(org.osgi.service.event.Event)
     */
    protected void handleMemoryEvent(Event event) {
      /* if running low on memory then this cache can be cleared
       * and rebuilt at the expense of processing time
       */
      fNotFoundClasses.clear();
      fClassMap.clear();
    }

  }

  class TagLibraryInfoImpl extends TagLibraryInfo {
    TLDElementDeclaration decl;

    TagLibraryInfoImpl(String prefix, String uri, TLDElementDeclaration decl){
      super(prefix, uri);
      this.decl = decl;
    }

    public String getURI() {
      if (Platform.inDebugMode())
        new NotImplementedException().printStackTrace();
      return super.getURI();
    }

    public String getPrefixString() {
      if (Platform.inDebugMode())
        new NotImplementedException().printStackTrace();
      return super.getPrefixString();
    }

    public String getShortName() {
      return ((TLDDocument)decl.getOwnerDocument()).getShortname();
    }

    public String getReliableURN() {
      return ((TLDDocument)decl.getOwnerDocument()).getUri();
    }

    public String getInfoString() {
      return ((TLDDocument)decl.getOwnerDocument()).getInfo();
    }

    public String getRequiredVersion() {
      return ((TLDDocument)decl.getOwnerDocument()).getJspversion();
    }

    public TagInfo[] getTags() {
      if (Platform.inDebugMode())
        new NotImplementedException().printStackTrace();
      return super.getTags();
    }

    public TagFileInfo[] getTagFiles() {
      if (Platform.inDebugMode())
        new NotImplementedException().printStackTrace();
      return super.getTagFiles();
    }

    public TagInfo getTag(String shortname) {
      if (Platform.inDebugMode())
        new NotImplementedException().printStackTrace();
      return super.getTag(shortname);
    }

    public TagFileInfo getTagFile(String shortname) {
      if (Platform.inDebugMode())
        new NotImplementedException().printStackTrace();
      return super.getTagFile(shortname);
    }

    public FunctionInfo[] getFunctions() {
      if (Platform.inDebugMode())
        new NotImplementedException().printStackTrace();
      return super.getFunctions();
    }

    public FunctionInfo getFunction(String name) {
      new NotImplementedException(name).printStackTrace();
      return super.getFunction(name);
    }

    public TagLibraryInfo[] getTagLibraryInfos()  {
      if (Platform.inDebugMode())
        new NotImplementedException().printStackTrace();
      return new TagLibraryInfo[] { this };
    }
  }
}
TOP

Related Classes of org.eclipse.jst.jsp.core.internal.taglib.TaglibHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.