001/*
002 * Copyright (c) 2004-2010, Kohsuke Kawaguchi
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification, are permitted provided
006 * that the following conditions are met:
007 *
008 *     * Redistributions of source code must retain the above copyright notice, this list of
009 *       conditions and the following disclaimer.
010 *     * Redistributions in binary form must reproduce the above copyright notice, this list of
011 *       conditions and the following disclaimer in the documentation and/or other materials
012 *       provided with the distribution.
013 *
014 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
015 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
016 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
017 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
018 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
019 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
020 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
021 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
022 */
023
024package org.kohsuke.stapler.jelly;
025
026import org.apache.commons.jelly.JellyContext;
027import org.apache.commons.jelly.JellyException;
028import org.apache.commons.jelly.JellyTagException;
029import org.apache.commons.jelly.Script;
030import org.apache.commons.jelly.TagLibrary;
031import org.apache.commons.jelly.XMLOutput;
032import org.apache.commons.jelly.impl.TagScript;
033import org.xml.sax.Attributes;
034
035import javax.servlet.http.HttpServletRequest;
036import java.util.HashSet;
037import java.util.Set;
038
039/**
040 * @author Kohsuke Kawaguchi
041 */
042public class StaplerTagLibrary extends TagLibrary {
043    public StaplerTagLibrary() {
044        registerTag("adjunct",AdjunctTag.class);
045        registerTag("bind",BindTag.class);
046        registerTag("compress",CompressTag.class);
047        registerTag("contentType",ContentTypeTag.class);
048        registerTag("copyStream",CopyStreamTag.class);
049        registerTag("doctype",DoctypeTag.class);
050        registerTag("findAncestor",FindAncestorTag.class);
051        registerTag("header",HeaderTag.class);   // deprecated. for compatibility
052        registerTag("addHeader",HeaderTag.class);
053        registerTag("setHeader",SetHeaderTag.class);
054        registerTag("include",IncludeTag.class);
055        registerTag("isUserInRole",IsUserInRoleTag.class);
056        registerTag("nbsp",NbspTag.class);
057        registerTag("out",OutTag.class);
058        registerTag("parentScope",ParentScopeTag.class);
059        registerTag("redirect",RedirectTag.class);
060        registerTag("statusCode",StatusCodeTag.class);
061        registerTag("structuredMessageArgument",StructuredMessageArgumentTag.class);
062        registerTag("structuredMessageFormat",StructuredMessageFormatTag.class);
063    }
064
065    @Override
066    public TagScript createTagScript(String name, Attributes attributes) throws JellyException {
067        // performance optimization
068        if (name.equals("documentation"))
069            return new TagScript() {
070                public void run(JellyContext context, XMLOutput output) throws JellyTagException {
071                    // noop
072                }
073
074                @Override
075                public void setTagBody(Script tagBody) {
076                    // noop, we don't evaluate the body, so don't even keep it in memory.
077                }
078            };
079
080        if (name.equals("getOutput"))
081            return new TagScript() {
082                /**
083                 * Adds {@link XMLOutput} to the context.
084                 */
085                public void run(JellyContext context, XMLOutput output) throws JellyTagException {
086                    context.setVariable(getAttribute("var").evaluateAsString(context),output);
087                }
088            };
089
090        if (name.equals("once"))
091            return new TagScript() {
092                /**
093                 * Adds {@link XMLOutput} to the context.
094                 */
095                public void run(JellyContext context, XMLOutput output) throws JellyTagException {
096                    HttpServletRequest request = (HttpServletRequest)context.getVariable("request");
097                    Set<String> executedScripts = (Set<String>) request.getAttribute(ONCE_TAG_KEY);
098                    if(executedScripts==null)
099                        request.setAttribute(ONCE_TAG_KEY,executedScripts=new HashSet<String>());
100
101                    String key = getFileName()+':'+getLineNumber()+':'+getColumnNumber();
102
103                    if(executedScripts.add(key)) // run it just for the first time
104                        getTagBody().run(context,output);
105                }
106            };
107
108        return super.createTagScript(name, attributes);
109    }
110
111    private static final String ONCE_TAG_KEY = "stapler.once";
112}