Skip to main content

This CGIT instance is deprecated, and repositories have been moved to Gitlab or Github. See the repository descriptions for specific locations.

summaryrefslogblamecommitdiffstats
blob: 0e4608b994a4d0a52cdfc42587ec8ceab34d14d4 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                                                                                 




                           


                                                  
                                                















































































































































































































































                                                                                                                                                                                                       
                                                                                                                                                         



























































































































                                                                                                                                                                                                                                              
                              

                                      




                                                                                                       




















                                                          
/*******************************************************************************
 * Copyright (c) 2004 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.java;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
import org.eclipse.jst.jsp.core.internal.Logger;
import org.eclipse.jst.jsp.core.internal.parser.JSPSourceParser;
import org.eclipse.wst.common.contentmodel.CMDocument;
import org.eclipse.wst.common.contentmodel.CMNode;
import org.eclipse.wst.sse.core.parser.BlockMarker;
import org.eclipse.wst.sse.core.parser.StructuredDocumentRegionHandler;
import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.text.ITextRegion;
import org.eclipse.wst.sse.core.util.Debug;
import org.eclipse.wst.sse.core.util.StringUtils;
import org.eclipse.wst.xml.core.jsp.model.parser.temp.XMLJSPRegionContexts;
import org.eclipse.wst.xml.core.parser.XMLRegionContext;


/**
 * Parser/helper class for JSPTranslator.  Used for parsing XML-JSP regions (in a script block)
 * A lot of logic borrowed from TLDCMDocumentManager.  There should be only one XMLJSPRegionHelper per text file
 * 
 * @author pavery
 */
class XMLJSPRegionHelper implements StructuredDocumentRegionHandler {
	private final JSPTranslator fTranslator;
	protected JSPSourceParser fLocalParser = null;
	protected String fTextToParse = null;
	// need this if not at the start of the document (eg. parsing just a script block)
	protected int fStartOfTextToParse = 0;
	// buffers for text that this class parses	
	protected List fScriptlets = new ArrayList();
	protected List fExpressions = new ArrayList();
	protected List fDeclarations = new ArrayList();
	// name of the open tag that was last handled (if we are interested in it)
	protected String fTagname = null;
	protected String fTextBefore = ""; //$NON-NLS-1$
	protected String fUnescapedText = ""; //$NON-NLS-1$
	protected String fStrippedText = ""; //$NON-NLS-1$
	// for reconciling cursor position later
	int fPossibleOwner = JSPTranslator.SCRIPTLET;

	public XMLJSPRegionHelper(JSPTranslator translator) {
		getLocalParser().addStructuredDocumentRegionHandler(this);
		this.fTranslator = translator;
	}

	protected JSPSourceParser getLocalParser() {
		if (fLocalParser == null)
			fLocalParser = new JSPSourceParser();
		return fLocalParser;
	}

	public void addBlockMarker(BlockMarker marker) {
		fLocalParser.addBlockMarker(marker);
	}

	public void reset(String textToParse) {
		reset(textToParse, 0);
	}

	public void reset(String textToParse, int start) {
		fStartOfTextToParse = start;
		getLocalParser().reset(textToParse);
		fTextToParse = textToParse;
	}

	public void forceParse() {
		getLocalParser().getDocumentRegions();
		fLocalParser = null;
	}

	/*
	 * parse an entire file
	 */
	public void parse(String filename) {
		// from outer class
		List blockMarkers = this.fTranslator.getBlockMarkers();
		reset(getContents(filename));
		// this adds the current markers from the outer class list
		// to this parser so parsing works correctly
		for (int i = 0; i < blockMarkers.size(); i++) {
			addBlockMarker((BlockMarker) blockMarkers.get(i));
		}
		forceParse();
	}

	/*
	 * writes out scriptlet, expression, and declaration buffers
	 * to the ongoing buffers in the JSPTranslator (calls to outer JSPTranslator methods)
	 */
	public void writeToBuffers() {
		IStructuredDocumentRegion currentNode = fTranslator.getCurrentNode();
		for (int i = 0; i < fScriptlets.size(); i++) {
			this.fTranslator.translateScriptletString((String) fScriptlets.get(i), currentNode, currentNode.getStartOffset(), currentNode.getLength());
		}
		for (int i = 0; i < fExpressions.size(); i++) {
			this.fTranslator.translateExpressionString((String) fExpressions.get(i), currentNode, currentNode.getStartOffset(), currentNode.getLength());
		}
		for (int i = 0; i < fDeclarations.size(); i++) {
			this.fTranslator.translateDeclarationString((String) fDeclarations.get(i), currentNode, currentNode.getStartOffset(), currentNode.getLength());
		}
	}

	/*
	 * listens to parser node parsed events
	 * adds to local scriplet, expression, declaration buffers
	 * determines which type of region the cursor is in, and adjusts cursor offset accordingly 
	 */
	public void nodeParsed(IStructuredDocumentRegion sdRegion) {
		//				System.out.println("tagname > " + fTagname);
		//				System.out.println("sdRegion > " + sdRegion.getType());
		//				System.out.println("sdRegion text is >> " + fTextToParse.substring(sdRegion.getStartOffset(), sdRegion.getEndOffset()));
		//				System.out.println("+++=======================");
		try {
			if (isJSPStartRegion(sdRegion)) {
				String nameStr = getRegionName(sdRegion);
				if (isJSPRegion(nameStr))
					fTagname = nameStr;
				else
					fTagname = null;
			}
			else if (sdRegion.getFirstRegion().getType() == XMLJSPRegionContexts.JSP_CONTENT) {
				if (fTagname != null) {
					// assign contents to one of the tables
					if (isScriptlet(fTagname)) {
						processScriptlet(sdRegion);
					}
					else if (isExpression(fTagname)) {
						processExpression(sdRegion);
					}
					else if (isDeclaration(fTagname)) {
						processDeclaration(sdRegion);
					}
					else {
						processOtherRegions(sdRegion);
					}
				}
			}
			else if (sdRegion.getFirstRegion().getType() == XMLRegionContext.XML_CONTENT) {
				if (fTagname != null) {
					processUseBean(sdRegion);
					processOtherRegions(sdRegion);
				}
			}
			else {
				fTagname = null;
			}
			// this updates cursor position
			checkCursorInRegion(sdRegion);
		}
		catch (Exception e) {
			// logging this exception that I've seen a couple of times...
			Logger.logException("XMLJSPRegionHelper: exception in node parsing", e); //$NON-NLS-1$
		}
	}

	public void resetNodes() {
		// do nothing
	}

	private void checkCursorInRegion(IStructuredDocumentRegion sdRegion) {
		// if cursor is in this region...
		if (this.fTranslator.getSourcePosition() >= fStartOfTextToParse + sdRegion.getStartOffset() && this.fTranslator.getSourcePosition() <= fStartOfTextToParse + sdRegion.getEndOffset()) {
			int endOfNameTag = sdRegion.getStartOffset();
			int offset = fTextBefore.length() - fStrippedText.length();
			// offset in addtion to what's already in the buffer
			this.fTranslator.setRelativeOffset(this.fTranslator.getSourcePosition() - (fStartOfTextToParse + endOfNameTag) - offset);
			// outer class method
			this.fTranslator.setCursorOwner(fPossibleOwner);
			// add length of what's already in the buffer
			this.fTranslator.setRelativeOffset(this.fTranslator.getRelativeOffset() + this.fTranslator.getCursorOwner().length());
			if (fPossibleOwner == JSPTranslator.EXPRESSION) {
				// add length of expression prefix if necessary...
				this.fTranslator.setRelativeOffset(this.fTranslator.getRelativeOffset() + JSPTranslator.EXPRESSION_PREFIX.length());
			}
		}
	}

	protected void processDeclaration(IStructuredDocumentRegion sdRegion) {
		prepareText(sdRegion);
		fDeclarations.add(fStrippedText);
		fPossibleOwner = JSPTranslator.DECLARATION;
	}

	protected void processExpression(IStructuredDocumentRegion sdRegion) {
		prepareText(sdRegion);
		fExpressions.add(fStrippedText);
		fPossibleOwner = JSPTranslator.EXPRESSION;
	}

	protected void processScriptlet(IStructuredDocumentRegion sdRegion) {
		prepareText(sdRegion);
		fScriptlets.add(fStrippedText);
		fPossibleOwner = JSPTranslator.SCRIPTLET;
	}

	/*
	 * Substitutes values for entity references, strips CDATA tags, and keeps
	 * track of string length(s) for cursor position calculation later.
	 * @param sdRegion
	 */
	protected void prepareText(IStructuredDocumentRegion sdRegion) {
		fTextBefore = fTextToParse.substring(sdRegion.getStartOffset(), sdRegion.getEndOffset());
		fUnescapedText = EscapedTextUtil.getUnescapedText(fTextBefore);
		fStrippedText = this.fTranslator.stripCDATA(fUnescapedText);
	}

	protected void processUseBean(IStructuredDocumentRegion sdRegion) {
		if (fTagname != null && isUseBean(fTagname)) {
			// previous region has the actual attributes
			sdRegion = sdRegion.getPrevious();
			String beanClass, beanType, beanId, beanDecl = ""; //$NON-NLS-1$
			beanClass = getAttributeValue("class", sdRegion); //$NON-NLS-1$
			beanType = getAttributeValue("type", sdRegion); //$NON-NLS-1$
			beanId = getAttributeValue("id", sdRegion); //$NON-NLS-1$
			if (beanClass != "") //$NON-NLS-1$
				beanDecl = beanClass + " " + beanId + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
			else
				beanDecl = beanType + " " + beanId + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
			fScriptlets.add(beanDecl);
			fPossibleOwner = JSPTranslator.SCRIPTLET;
		}
	}

	protected void processOtherRegions(IStructuredDocumentRegion sdRegion) {
		processIncludeDirective(sdRegion);
		processPageDirective(sdRegion);
	}

	protected void processIncludeDirective(IStructuredDocumentRegion sdRegion) {
		if (isIncludeDirective(fTagname)) {
			// the directive name region itself contains the attrs...
			if (sdRegion.getRegions().get(0).getType() == XMLRegionContext.XML_CONTENT)
				sdRegion = sdRegion.getPrevious();
			String fileLocation = getAttributeValue("file", sdRegion); //$NON-NLS-1$
			this.fTranslator.handleIncludeFile(fileLocation);
		}
		else if (isPossibleCustomTag(fTagname)) {
			// this custom tag may define variables
			this.fTranslator.addTaglibVariables(fTagname);
		}
		else if (isTaglibDirective(fTagname)) {
			// also add the ones created here to the parent document
			String prefix = getAttributeValue("prefix", sdRegion); //$NON-NLS-1$
			List docs = this.fTranslator.getTLDCMDocumentManager().getCMDocumentTrackers(prefix, this.fTranslator.getCurrentNode().getEnd());
			Iterator it = docs.iterator();
			Iterator elements = null;
			CMNode node = null;
			CMDocument doc = null;
			BlockMarker marker = null;
			while (it.hasNext()) {
				doc = (CMDocument) it.next();
				elements = doc.getElements().iterator();
				while (elements.hasNext()) {
					node = (CMNode) elements.next();
					marker = new BlockMarker(node.getNodeName(), null, XMLJSPRegionContexts.JSP_CONTENT, true);
					// global scope is OK because we have encountered this <@taglib> directive
					// so it all markers from it should will be in scope
					// add to this local parser
					addBlockMarker(marker);
					// add to outer class marker list, for 
					this.fTranslator.getBlockMarkers().add(marker);
				}
			}
		}
	}

	protected void processPageDirective(IStructuredDocumentRegion sdRegion) {
		if (isPageDirective(fTagname)) {
			while (sdRegion != null) {
				if (sdRegion.getType() == XMLJSPRegionContexts.JSP_DIRECTIVE_NAME)
					break;
				sdRegion = sdRegion.getPrevious();
			}
			String importValue = getAttributeValue("import", sdRegion); //$NON-NLS-1$
			if (importValue != "") //$NON-NLS-1$
				this.fTranslator.addImports(importValue);
		}
	}

	/*
	 * convenience method to get an attribute value from attribute name
	 */
	protected String getAttributeValue(String attrName, IStructuredDocumentRegion sdRegion) {
		String sdRegionText = fTextToParse.substring(sdRegion.getStartOffset(), sdRegion.getEndOffset());
		String textRegionText, attrValue = ""; //$NON-NLS-1$
		Iterator it = sdRegion.getRegions().iterator();
		ITextRegion nameRegion, valueRegion = null;
		while (it.hasNext()) {
			nameRegion = (ITextRegion) it.next();
			if (nameRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_NAME) {
				textRegionText = sdRegionText.substring(nameRegion.getStart(), nameRegion.getEnd());
				if (textRegionText.equalsIgnoreCase(attrName)) {
					while (it.hasNext()) {
						valueRegion = (ITextRegion) it.next();
						if (valueRegion.getType() == XMLRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
							attrValue = sdRegionText.substring(valueRegion.getStart(), valueRegion.getEnd());
							break; // inner
						}
					}
					break; // outer
				}
			}
		}
		return StringUtils.stripQuotes(attrValue);
	}

	// these methods determine what content gets added to the local scriplet, expression, declaration buffers
	/*
	 * return true for elements whose contents we might want to add to the java file we are building
	 */
	protected boolean isJSPStartRegion(IStructuredDocumentRegion sdRegion) {
		return (sdRegion.getFirstRegion().getType() == XMLRegionContext.XML_TAG_OPEN || sdRegion.getFirstRegion().getType() == XMLJSPRegionContexts.JSP_DIRECTIVE_OPEN);
	}

	protected boolean isJSPRegion(String tagName) {
		return isDeclaration(tagName) || isExpression(tagName) || isScriptlet(tagName) || isUseBean(tagName) || isIncludeDirective(tagName) || isPossibleCustomTag(tagName) || isTaglibDirective(tagName) || isPageDirective(tagName);
	}

	protected boolean isDeclaration(String tagName) {
		return tagName.equalsIgnoreCase("jsp:declaration"); //$NON-NLS-1$		
	}

	protected boolean isExpression(String tagName) {
		return tagName.equalsIgnoreCase("jsp:expression"); //$NON-NLS-1$		
	}

	protected boolean isScriptlet(String tagName) {
		return tagName.equalsIgnoreCase("jsp:scriptlet"); //$NON-NLS-1$
	}

	protected boolean isUseBean(String tagName) {
		return tagName.equalsIgnoreCase("jsp:useBean"); //$NON-NLS-1$
	}

	protected boolean isIncludeDirective(String tagName) {
		return tagName.equalsIgnoreCase("jsp:directive.include"); //$NON-NLS-1$
	}

	protected boolean isPossibleCustomTag(String tagName) {
		return tagName.indexOf(":") > 1; //$NON-NLS-1$
	}

	protected boolean isTaglibDirective(String tagName) {
		return tagName.equalsIgnoreCase("jsp:directive.taglib"); //$NON-NLS-1$
	}

	protected boolean isPageDirective(String tagName) {
		return tagName.equalsIgnoreCase("jsp:directive.page"); //$NON-NLS-1$
	}

	protected String getRegionName(IStructuredDocumentRegion sdRegion) {
		ITextRegion nameRegion = null;
		String nameStr = ""; //$NON-NLS-1$
		int size = sdRegion.getRegions().size();
		if (size > 1) {
			// presumably XML-JSP <jsp:scriptlet> | <jsp:expression> | <jsp:declaration>
			nameRegion = sdRegion.getRegions().get(1);
			nameStr = fTextToParse.substring(sdRegion.getStartOffset(nameRegion), sdRegion.getTextEndOffset(nameRegion));
		}
		return nameStr.trim();
	}

	/*
	 * get the contents of a file as a String
	 */
	protected String getContents(String fileName) {
		StringBuffer s = new StringBuffer();
		int c = 0;
		int count = 0;
		InputStream is = null;
		try {
			// filename is now going to be project relative beacuse of
			// our use of FileBuffers
			IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(fileName));
			is = f.getContents();
			while ((c = is.read()) != -1) {
				count++;
				s.append((char) c);
			}
		}
		catch (Exception e) {
			if (Debug.debugStructuredDocument)
				e.printStackTrace();
		}
		finally {
			try {
				if (is != null) {
					is.close();
				}
			}
			catch (Exception e) {
				// nothing to do
			}
		}
		return s.toString();
	}
}

Back to the top