001/*
002 * (C) Copyright 2006-2008 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     bstefanescu
016 *
017 * $Id$
018 */
019
020package org.nuxeo.ecm.webengine.model;
021
022import org.apache.commons.logging.Log;
023import org.apache.commons.logging.LogFactory;
024
025import java.io.IOException;
026import java.io.OutputStream;
027import java.io.OutputStreamWriter;
028import java.io.StringWriter;
029import java.io.Writer;
030import java.util.HashMap;
031import java.util.Map;
032import java.io.UnsupportedEncodingException;
033import java.net.SocketException;
034
035import org.nuxeo.common.utils.ExceptionUtils;
036import org.nuxeo.ecm.webengine.WebException;
037import org.nuxeo.ecm.webengine.scripting.ScriptFile;
038
039/**
040 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
041 */
042public class Template {
043
044    private static final Log log = LogFactory.getLog(Template.class);
045
046    protected final Resource resource;
047
048    protected Map<String, Object> args;
049
050    protected ScriptFile script;
051
052    protected WebContext ctx;
053
054    protected Template(WebContext ctx, Resource resource, ScriptFile script) {
055        this.ctx = ctx;
056        this.resource = resource;
057        this.script = script;
058        if (this.ctx == null && this.resource != null) {
059            this.ctx = this.resource.getContext();
060        }
061    }
062
063    public Template(WebContext ctx, String fileName) {
064        this(ctx, null, null);
065        resolve(fileName);
066    }
067
068    public Template(Resource resource, String fileName) {
069        this(resource.getContext(), resource, null);
070        resolve(fileName);
071    }
072
073    public Template(WebContext ctx, ScriptFile script) {
074        this(ctx, null, script);
075    }
076
077    public Template(Resource resource, ScriptFile script) {
078        this(resource.getContext(), resource, script);
079    }
080
081    public Template arg(String key, Object value) {
082        if (args == null) {
083            args = new HashMap<String, Object>();
084        }
085        args.put(key, value);
086        return this;
087    }
088
089    public Template args(Map<String, Object> args) {
090        this.args = args;
091        return this;
092    }
093
094    public Map<String, Object> args() {
095        return args;
096    }
097
098    public Resource resource() {
099        return resource;
100    }
101
102    protected void resolve(String fileName) {
103        if (resource != null) {
104            script = resource.getType().getView(ctx.getModule(), fileName);
105        } else {
106            script = ctx.getModule().getFile(fileName);
107        }
108    }
109
110    public ScriptFile script() {
111        return script;
112    }
113
114    public void render(OutputStream out) throws WebException {
115        Writer w;
116        try {
117            w = new OutputStreamWriter(out, "UTF-8");
118        } catch (UnsupportedEncodingException e) {
119            throw WebException.wrap("Failed to create output stream: unsupported encoding", e);
120        }
121        ctx.render(script(), args, w);
122        try {
123            w.flush();
124        } catch (IOException e) {
125            if (ExceptionUtils.getRootCause(e) instanceof SocketException) {
126                log.debug("Output socket closed: failed to flush response");
127            } else {
128                throw WebException.wrap("Failed to flush response", e);
129            }
130        }
131    }
132
133    public String render() {
134        StringWriter w = new StringWriter();
135        ctx.render(script(), args, w);
136        w.flush();
137        return w.getBuffer().toString();
138    }
139
140}