001/*
002 * (C) Copyright 2006-2008 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     bstefanescu
018 *
019 * $Id$
020 */
021
022package org.nuxeo.ecm.webengine.model;
023
024import org.apache.commons.logging.Log;
025import org.apache.commons.logging.LogFactory;
026
027import java.io.IOException;
028import java.io.OutputStream;
029import java.io.OutputStreamWriter;
030import java.io.StringWriter;
031import java.io.Writer;
032import java.util.HashMap;
033import java.util.Map;
034import java.io.UnsupportedEncodingException;
035import java.net.SocketException;
036
037import org.nuxeo.common.utils.ExceptionUtils;
038import org.nuxeo.ecm.webengine.WebException;
039import org.nuxeo.ecm.webengine.scripting.ScriptFile;
040
041/**
042 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
043 */
044public class Template {
045
046    private static final Log log = LogFactory.getLog(Template.class);
047
048    protected final Resource resource;
049
050    protected Map<String, Object> args;
051
052    protected ScriptFile script;
053
054    protected WebContext ctx;
055
056    protected Template(WebContext ctx, Resource resource, ScriptFile script) {
057        this.ctx = ctx;
058        this.resource = resource;
059        this.script = script;
060        if (this.ctx == null && this.resource != null) {
061            this.ctx = this.resource.getContext();
062        }
063    }
064
065    public Template(WebContext ctx, String fileName) {
066        this(ctx, null, null);
067        resolve(fileName);
068    }
069
070    public Template(Resource resource, String fileName) {
071        this(resource.getContext(), resource, null);
072        resolve(fileName);
073    }
074
075    public Template(WebContext ctx, ScriptFile script) {
076        this(ctx, null, script);
077    }
078
079    public Template(Resource resource, ScriptFile script) {
080        this(resource.getContext(), resource, script);
081    }
082
083    public Template arg(String key, Object value) {
084        if (args == null) {
085            args = new HashMap<String, Object>();
086        }
087        args.put(key, value);
088        return this;
089    }
090
091    public Template args(Map<String, Object> args) {
092        this.args = args;
093        return this;
094    }
095
096    public Map<String, Object> args() {
097        return args;
098    }
099
100    public Resource resource() {
101        return resource;
102    }
103
104    protected void resolve(String fileName) {
105        if (resource != null) {
106            script = resource.getType().getView(ctx.getModule(), fileName);
107        } else {
108            script = ctx.getModule().getFile(fileName);
109        }
110    }
111
112    public ScriptFile script() {
113        return script;
114    }
115
116    public void render(OutputStream out) throws WebException {
117        Writer w;
118        try {
119            w = new OutputStreamWriter(out, "UTF-8");
120        } catch (UnsupportedEncodingException e) {
121            throw WebException.wrap("Failed to create output stream: unsupported encoding", e);
122        }
123        ctx.render(script(), args, w);
124        try {
125            w.flush();
126        } catch (IOException e) {
127            if (ExceptionUtils.getRootCause(e) instanceof SocketException) {
128                log.debug("Output socket closed: failed to flush response");
129            } else {
130                throw WebException.wrap("Failed to flush response", e);
131            }
132        }
133    }
134
135    public String render() {
136        StringWriter w = new StringWriter();
137        ctx.render(script(), args, w);
138        w.flush();
139        return w.getBuffer().toString();
140    }
141
142}