private void html() { if (!finalPass) return; LOG.debug("parse: html"); String text = scan.getToken(); if (text.length() == 0) { return; } // If we detect it is all whitespace, we need to keep it for later // If it is not whitespace, we need to flush any whitespace we do have boolean contentIsWhitespace = !Pattern.compile("\\S").matcher(text).find(); if (!contentIsWhitespace && currentlyBufferingWhitespace) { flushBufferedWhiteSpace(); } else { currentlyBufferingWhitespace = contentIsWhitespace; } // We need to know if the last content output was not whitespace, for tag safety checks previousContentWasNonWhitespace = !contentIsWhitespace; if (currentlyBufferingWhitespace) { whitespaceBuffer.append(text); } else { appendHtmlPart(text); } }
private void scriptletExpr() { if (!finalPass) { return; } LOG.debug("parse: expr"); String text = scan.getToken().trim(); out.printlnToResponse(text); }
private void script(boolean gsp) { flushTagBuffering(); if (!finalPass) return; LOG.debug("parse: script"); out.println(); write(scan.getToken().trim(), gsp); out.println(); out.println(); }
private void declare(boolean gsp) { if (finalPass) { return; } LOG.debug("parse: declare"); out.println(); write(scan.getToken().trim(), gsp); out.println(); out.println(); }
private void expr() { if (!finalPass) return; LOG.debug("parse: expr"); String text = scan.getToken().trim(); text = getExpressionText(text); if (text != null && text.length() > 2 && text.startsWith("(") && text.endsWith(")")) { out.printlnToResponse( GroovyPage.EXPRESSION_OUT_STATEMENT, text.substring(1, text.length() - 1)); } else { out.printlnToResponse(GroovyPage.EXPRESSION_OUT_STATEMENT, text); } }
private void direct() { if (finalPass) { return; } LOG.debug("parse: direct"); String text = scan.getToken(); text = text.trim(); if (text.startsWith(TAGLIB_DIRECTIVE)) { directJspTagLib(text); } else { directPage(text); } }
public void generateGsp(Writer target, boolean precompileMode) { this.precompileMode = precompileMode; out = new GSPWriter(target, this); if (packageName != null && packageName.length() > 0) { out.println("package " + packageName); out.println(); } page(); finalPass = true; scan.reset(); previousContentWasNonWhitespace = false; currentlyBufferingWhitespace = false; page(); out.close(); scan = null; }
private void endTag() { if (!finalPass) return; String tagName = scan.getToken().trim(); String ns = scan.getNamespace(); if (tagMetaStack.isEmpty()) throw new GrailsTagException( "Found closing Grails tag with no opening [" + tagName + "]", pageName, getCurrentOutputLineNumber()); TagMeta tm = tagMetaStack.pop(); String lastInStack = tm.name; String lastNamespaceInStack = tm.namespace; // if the tag name is blank then it has been closed by the start tag ie <tag /> if (GrailsStringUtils.isBlank(tagName)) { tagName = lastInStack; } if (!lastInStack.equals(tagName) || !lastNamespaceInStack.equals(ns)) { throw new GrailsTagException( "Grails tag [" + lastNamespaceInStack + ":" + lastInStack + "] was not closed", pageName, getCurrentOutputLineNumber()); } if (GroovyPage.DEFAULT_NAMESPACE.equals(ns) && tagRegistry.isSyntaxTag(tagName)) { if (tm.instance instanceof GroovySyntaxTag) { GroovySyntaxTag tag = (GroovySyntaxTag) tm.instance; tag.doEndTag(); } else { throw new GrailsTagException( "Grails tag [" + tagName + "] was not closed", pageName, getCurrentOutputLineNumber()); } } else { int bodyTagIndex = -1; if (!tm.emptyTag && !tm.bufferMode) { bodyTagIndex = tagIndex; out.println("})"); closureLevel--; } if (tm.bufferMode && tm.bufferPartNumber != -1) { if (!bodyVarsDefined.contains(tm.tagIndex)) { // out.print("def "); bodyVarsDefined.add(tm.tagIndex); } out.println("createClosureForHtmlPart(" + tm.bufferPartNumber + ", " + tm.tagIndex + ")"); bodyTagIndex = tm.tagIndex; tm.bufferMode = false; } if (jspTags.containsKey(ns)) { String uri = jspTags.get(ns); out.println("jspTag = getJspTag('" + uri + "', '" + tagName + "')"); out.println( "if (!jspTag) throw new GrailsTagException('Unknown JSP tag " + ns + ":" + tagName + "')"); out.print("jspTag.doTag(out," + attrsVarsMapDefinition.get(tagIndex) + ","); if (bodyTagIndex > -1) { out.print("getBodyClosure(" + bodyTagIndex + ")"); } else { out.print("null"); } out.println(")"); } else { if (tm.hasAttributes) { out.println( "invokeTag('" + tagName + "','" + ns + "'," + getCurrentOutputLineNumber() + "," + attrsVarsMapDefinition.get(tagIndex) + "," + bodyTagIndex + ")"); } else { out.println( "invokeTag('" + tagName + "','" + ns + "'," + getCurrentOutputLineNumber() + ",[:]," + bodyTagIndex + ")"); } } } tm.bufferMode = false; tagIndex--; }
private void page() { LOG.debug("parse: page"); if (finalPass) { out.println(); if (pluginAnnotation != null) { out.println(pluginAnnotation); } out.print("class "); out.print(className); out.println(" extends GroovyPage {"); out.println( "public String getGroovyPageFileName() { \"" + pageName.replaceAll("\\\\", "/") + "\" }"); out.println("public Object run() {"); /* out.println("def params = binding.params"); out.println("def request = binding.request"); out.println("def flash = binding.flash"); out.println("def response = binding.response"); */ out.println("Writer " + GroovyPage.OUT + " = getOut()"); out.println("Writer " + GroovyPage.EXPRESSION_OUT + " = getExpressionOut()"); // out.println("JspTagLib jspTag"); if (sitemeshPreprocessMode) { out.println("registerSitemeshPreprocessMode()"); } } loop: for (; ; ) { if (doNextScan) { state = scan.nextToken(); } else { doNextScan = true; } // Flush any buffered whitespace if there's not a possibility of more whitespace // or a new tag which will handle flushing as necessary if ((state != GSTART_TAG) && (state != HTML)) { flushBufferedWhiteSpace(); previousContentWasNonWhitespace = false; // well, we don't know } switch (state) { case EOF: break loop; case HTML: html(); break; case JEXPR: scriptletExpr(); break; case JSCRIPT: script(false); break; case JDIRECT: direct(); break; case JDECLAR: declare(false); break; case GEXPR: expr(); break; case GSCRIPT: script(true); break; case GDIRECT: direct(); break; case GDECLAR: declare(true); break; case GSTART_TAG: startTag(); break; case GEND_EMPTY_TAG: case GEND_TAG: endTag(); break; } } if (finalPass) { if (!tagMetaStack.isEmpty()) { throw new GrailsTagException( "Grails tags were not closed! [" + tagMetaStack + "] in GSP " + pageName + "", pageName, getCurrentOutputLineNumber()); } out.println("}"); out.println("public static final Map " + CONSTANT_NAME_JSP_TAGS + " = new HashMap()"); if (jspTags != null && jspTags.size() > 0) { out.println("static {"); for (Map.Entry<String, String> entry : jspTags.entrySet()) { out.print("\t" + CONSTANT_NAME_JSP_TAGS + ".put('"); out.print(escapeGroovy(entry.getKey())); out.print("','"); out.print(escapeGroovy(entry.getValue())); out.println("')"); } out.println("}"); } out.println("protected void init() {"); out.println("\tthis.jspTags = " + CONSTANT_NAME_JSP_TAGS); out.println("}"); out.println( "public static final String " + CONSTANT_NAME_CONTENT_TYPE + " = '" + escapeGroovy(contentType) + "'"); out.println( "public static final long " + CONSTANT_NAME_LAST_MODIFIED + " = " + lastModified + "L"); out.println( "public static final String " + CONSTANT_NAME_EXPRESSION_CODEC + " = '" + escapeGroovy(expressionCodecDirectiveValue) + "'"); out.println( "public static final String " + CONSTANT_NAME_STATIC_CODEC + " = '" + escapeGroovy(staticCodecDirectiveValue) + "'"); out.println( "public static final String " + CONSTANT_NAME_OUT_CODEC + " = '" + escapeGroovy(outCodecDirectiveValue) + "'"); out.println( "public static final String " + CONSTANT_NAME_TAGLIB_CODEC + " = '" + escapeGroovy(taglibCodecDirectiveValue) + "'"); out.println("}"); if (shouldAddLineNumbers()) { addLineNumbers(); } } else { for (int i = 0; i < DEFAULT_IMPORTS.length; i++) { out.print("import "); out.println(DEFAULT_IMPORTS[i]); } } }
public int getCurrentOutputLineNumber() { return scan.getLineNumberForToken(); }
@SuppressWarnings({"unchecked", "rawtypes"}) private void startTag() { if (!finalPass) return; tagIndex++; String text; StringBuilder buf = new StringBuilder(scan.getToken()); String ns = scan.getNamespace(); boolean emptyTag = false; state = scan.nextToken(); while (state != HTML && state != GEND_TAG && state != GEND_EMPTY_TAG && state != EOF) { if (state == GTAG_EXPR) { buf.append("${"); buf.append(scan.getToken().trim()); buf.append("}"); } else { buf.append(scan.getToken()); } state = scan.nextToken(); } if (state == GEND_EMPTY_TAG) { emptyTag = true; } doNextScan = false; text = buf.toString(); String tagName; Map attrs = new LinkedHashMap(); Matcher m = Pattern.compile("\\s").matcher(text); if (m.find()) { // ignores carriage returns and new lines tagName = text.substring(0, m.start()); if (state != EOF) { String attrTokens = text.substring(m.start(), text.length()); populateMapWithAttributes(attrs, attrTokens); } } else { tagName = text; } if (state == EOF) { throw new GrailsTagException( "Unexpected end of file encountered parsing Tag [" + tagName + "] for " + className + ". Are you missing a closing brace '}'?", pageName, getCurrentOutputLineNumber()); } flushTagBuffering(); TagMeta tm = new TagMeta(); tm.name = tagName; tm.namespace = ns; tm.hasAttributes = !attrs.isEmpty(); tm.lineNumber = getCurrentOutputLineNumber(); tm.emptyTag = emptyTag; tm.tagIndex = tagIndex; tagMetaStack.push(tm); if (GroovyPage.DEFAULT_NAMESPACE.equals(ns) && tagRegistry.isSyntaxTag(tagName)) { if (tagContext == null) { tagContext = new HashMap<Object, Object>(); tagContext.put(GroovyPage.OUT, out); tagContext.put(GroovyPageParser.class, this); } GroovySyntaxTag tag = (GroovySyntaxTag) tagRegistry.newTag(tagName); tag.init(tagContext); tag.setAttributes(attrs); if (tag.isKeepPrecedingWhiteSpace() && currentlyBufferingWhitespace) { flushBufferedWhiteSpace(); } else if (!tag.isAllowPrecedingContent() && previousContentWasNonWhitespace) { throw new GrailsTagException( "Tag [" + tag.getName() + "] cannot have non-whitespace characters directly preceding it.", pageName, getCurrentOutputLineNumber()); } else { // If tag does not specify buffering of WS, we swallow it here clearBufferedWhiteSpace(); } tag.doStartTag(); tm.instance = tag; } else { // Custom taglibs have to always flush the whitespace, there's no // "allowPrecedingWhitespace" property on tags yet flushBufferedWhiteSpace(); if (attrs.size() > 0) { FastStringWriter buffer = new FastStringWriter(); buffer.print("["); for (Iterator<?> i = attrs.keySet().iterator(); i.hasNext(); ) { String name = (String) i.next(); String cleanedName = name; if (name.startsWith("\"") && name.endsWith("\"")) { cleanedName = "'" + name.substring(1, name.length() - 1) + "'"; } buffer.print(cleanedName); buffer.print(':'); buffer.print(getExpressionText(attrs.get(name).toString())); if (i.hasNext()) { buffer.print(','); } else { buffer.print("]"); } } attrsVarsMapDefinition.put(tagIndex, buffer.toString()); buffer.close(); } if (!emptyTag) { tm.bufferMode = true; } } }