001/*
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     bstefanescu
011 */
012package org.nuxeo.ecm.webengine.jaxrs.views;
013
014import java.io.File;
015import java.io.IOException;
016import java.io.OutputStream;
017import java.io.OutputStreamWriter;
018import java.io.Writer;
019import java.net.MalformedURLException;
020import java.net.URL;
021import java.util.HashMap;
022import java.util.Map;
023
024import org.nuxeo.ecm.platform.rendering.api.RenderingException;
025import org.nuxeo.ecm.platform.rendering.api.ResourceLocator;
026import org.nuxeo.ecm.platform.rendering.fm.FreemarkerEngine;
027import org.osgi.framework.Bundle;
028
029/**
030 * Template for compatibility with Nuxeo WebEngine
031 *
032 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
033 */
034public class TemplateView {
035
036    private static final FreemarkerEngine engine = new FreemarkerEngine(null, new Locator());
037
038    private static final Map<String, TemplateView> locators = new HashMap<String, TemplateView>();
039
040    public static URL resolveFile(File file) throws ViewNotFoundException {
041        if (!file.isFile()) {
042            throw new ViewNotFoundException(null, null, file.getAbsolutePath());
043        }
044        try {
045            return file.toURI().toURL();
046        } catch (MalformedURLException e) {
047            throw new ViewNotFoundException(e, null, file.getAbsolutePath());
048        }
049    }
050
051    public static URL resolveResource(Object owner, String name) throws ViewNotFoundException {
052        URL url = owner.getClass().getResource(name);
053        if (url == null) {
054            throw new ViewNotFoundException(null, owner, name);
055        }
056        return url;
057    }
058
059    public static URL resolveResourceFromBundle(Bundle bundle, String name) throws ViewNotFoundException {
060        URL url = bundle.getEntry(name);
061        if (url == null) {
062            throw new ViewNotFoundException(null, bundle, name);
063        }
064        return url;
065    }
066
067    private static URL resolveResource(Bundle bundle, Object owner, String name) throws ViewNotFoundException {
068        return bundle != null ? resolveResourceFromBundle(bundle, name) : resolveResource(owner, name);
069    }
070
071    protected Object owner;
072
073    protected final URL url;
074
075    protected final Map<String, Object> vars;
076
077    public TemplateView(String name) {
078        this(null, null, name);
079    }
080
081    public TemplateView(Object owner, String name) {
082        this(null, owner, name);
083    }
084
085    public TemplateView(Bundle bundle, Object owner, String name) {
086        this(owner, resolveResource(bundle, owner, name));
087    }
088
089    public TemplateView(File file) {
090        this(null, file);
091    }
092
093    public TemplateView(Object owner, File file) {
094        this(owner, resolveFile(file));
095    }
096
097    public TemplateView(URL url) {
098        this(null, url);
099    }
100
101    public TemplateView(Object owner, URL url) {
102        vars = new HashMap<String, Object>();
103        this.url = url;
104        if (owner != null) {
105            forObject(owner);
106        }
107    }
108
109    public TemplateView forObject(Object owner) {
110        this.owner = owner;
111        vars.put("This", owner);
112        return this;
113    }
114
115    public URL getUrl() {
116        return url;
117    }
118
119    public Object getOwner() {
120        return owner;
121    }
122
123    public TemplateView arg(String key, Object value) {
124        vars.put(key, value);
125        return this;
126    }
127
128    public void render(Writer writer) throws RenderingException, IOException {
129        String id = addLocator(this);
130        try {
131            engine.render(id, vars, writer);
132            writer.flush();
133        } finally {
134            removeLocator(id);
135        }
136    }
137
138    public void render(OutputStream out) throws RenderingException, IOException {
139        render(new OutputStreamWriter(out, "UTF-8"));
140    }
141
142    private static synchronized String addLocator(TemplateView view) {
143        String locatorId = "view:/" + view.getUrl().toExternalForm();
144        locators.put(locatorId, view);
145        return locatorId;
146    }
147
148    private static synchronized void removeLocator(String id) {
149        locators.remove(id);
150    }
151
152    private static synchronized TemplateView getLocator(String id) {
153        return locators.get(id);
154    }
155
156    static class Locator implements ResourceLocator {
157        @Override
158        public File getResourceFile(String key) {
159            return null;
160        }
161
162        @Override
163        public URL getResourceURL(String key) {
164            TemplateView view = getLocator(key);
165            if (view != null) {
166                return view.getUrl();
167            }
168            return null;
169        }
170    }
171
172}