public static Closure createOutputCapturingClosure( Object wrappedInstance, final Object body1, final GrailsWebRequest webRequest, boolean preferSubChunkWhenWritingToOtherBuffer) { if (body1 == null) { return EMPTY_BODY_CLOSURE; } else if (body1 instanceof GroovyPageTagBody) { GroovyPageTagBody gptb = (GroovyPageTagBody) body1; gptb.setPreferSubChunkWhenWritingToOtherBuffer(preferSubChunkWhenWritingToOtherBuffer); return gptb; } else if (body1 instanceof ConstantClosure) { return (Closure) body1; } else if (body1 instanceof Closure) { return new GroovyPageTagBody( wrappedInstance, webRequest, (Closure) body1, preferSubChunkWhenWritingToOtherBuffer); } else { return new ConstantClosure(body1); } }
public void invokeTag( String tagName, String tagNamespace, int lineNumber, Map attrs, Closure body) { // TODO custom namespace stuff needs to be generalized and pluggable if (tagNamespace.equals(TEMPLATE_NAMESPACE)) { final String tmpTagName = tagName; final Map tmpAttrs = attrs; tagName = "render"; tagNamespace = DEFAULT_NAMESPACE; attrs = new HashMap() { { put("model", tmpAttrs); put("template", tmpTagName); } }; } else if (tagNamespace.equals(LINK_NAMESPACE)) { final String tmpTagName = tagName; final Map tmpAttrs = attrs; tagName = "link"; tagNamespace = DEFAULT_NAMESPACE; attrs = new HashMap() { { if (tmpAttrs.size() > 0) { put("params", tmpAttrs); } put("mapping", tmpTagName); } }; } try { GroovyObject tagLib = getTagLib(tagNamespace, tagName); if (tagLib != null || gspTagLibraryLookup.hasNamespace(tagNamespace)) { if (tagLib != null) { boolean returnsObject = gspTagLibraryLookup.doesTagReturnObject(tagNamespace, tagName); Object tagLibProp = tagLib.getProperty(tagName); if (tagLibProp instanceof Closure) { Closure tag = (Closure) ((Closure) tagLibProp).clone(); Object tagresult = null; // GSP<->Sitemesh integration requires that the body or head subchunk isn't written to // output boolean preferSubChunkWhenWritingToOtherBuffer = resolvePreferSubChunk(tagNamespace, tagName); if (body instanceof GroovyPageTagBody && preferSubChunkWhenWritingToOtherBuffer) { ((GroovyPageTagBody) body).setPreferSubChunkWhenWritingToOtherBuffer(true); } switch (tag.getParameterTypes().length) { case 1: tagresult = tag.call(new Object[] {attrs}); if (returnsObject && tagresult != null && !(tagresult instanceof Writer)) { out.print(tagresult); } if (body != null && body != EMPTY_BODY_CLOSURE) { body.call(); } break; case 2: if (tag.getParameterTypes().length == 2) { tagresult = tag.call(new Object[] {attrs, (body != null) ? body : EMPTY_BODY_CLOSURE}); if (returnsObject && tagresult != null && !(tagresult instanceof Writer)) { out.print(tagresult); } } break; } } else { throw new GrailsTagException( "Tag [" + tagName + "] does not exist in tag library [" + tagLib.getClass().getName() + "]", getGroovyPageFileName(), lineNumber); } } else { throw new GrailsTagException( "Tag [" + tagName + "] does not exist. No tag library found for namespace: " + tagNamespace, getGroovyPageFileName(), lineNumber); } } else { out.append('<').append(tagNamespace).append(':').append(tagName); for (Object o : attrs.entrySet()) { Map.Entry entry = (Map.Entry) o; out.append(' '); out.append(entry.getKey()).append('='); String value = String.valueOf(entry.getValue()); // handle attribute value quotes & possible escaping " -> " boolean containsQuotes = (value.indexOf('"') > -1); boolean containsSingleQuote = (value.indexOf('\'') > -1); if (containsQuotes && !containsSingleQuote) { out.append('\'').append(value).append('\''); } else if (containsQuotes & containsSingleQuote) { out.append('\"').append(value.replaceAll("\"", """)).append('\"'); } else { out.append('\"').append(value).append('\"'); } } out.append('>'); if (body != null) { Object bodyOutput = body.call(); if (bodyOutput != null) out.print(bodyOutput); } out.append("</").append(tagNamespace).append(':').append(tagName).append('>'); } } catch (Throwable e) { if (LOG.isTraceEnabled()) { LOG.trace("Full exception for problem at " + getGroovyPageFileName() + ":" + lineNumber, e); } // The capture* tags are internal tags and not to be displayed to the user // hence we don't wrap the exception and simple rethrow it if (tagName.matches("capture(Body|Head|Meta|Title|Component)")) { RuntimeException rte = GrailsExceptionResolver.getFirstRuntimeException(e); if (rte == null) { throwRootCause(tagName, tagNamespace, lineNumber, e); } else { throw rte; } } else { throwRootCause(tagName, tagNamespace, lineNumber, e); } } }