001/*
002 * (C) Copyright 2006-2011 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.platform.rendering.fm;
023
024import java.io.File;
025import java.io.FileInputStream;
026import java.io.IOException;
027import java.io.InputStreamReader;
028import java.io.Reader;
029import java.net.MalformedURLException;
030import java.net.URL;
031
032import org.nuxeo.ecm.platform.rendering.api.ResourceLocator;
033
034import freemarker.cache.TemplateLoader;
035import freemarker.cache.URLTemplateLoader;
036
037/**
038 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
039 */
040public class ResourceTemplateLoader implements TemplateLoader {
041
042    protected ResourceLocator locator;
043
044    protected final MyURLTemplateLoader urlLoader;
045
046    protected final MyFileTemplateLoader fileLoader;
047
048    public ResourceTemplateLoader(ResourceLocator locator) {
049        this.locator = locator;
050        urlLoader = new MyURLTemplateLoader();
051        fileLoader = new MyFileTemplateLoader();
052    }
053
054    public void setLocator(ResourceLocator locator) {
055        this.locator = locator;
056    }
057
058    public ResourceLocator getLocator() {
059        return locator;
060    }
061
062    @Override
063    public void closeTemplateSource(Object templateSource) throws IOException {
064        if (templateSource instanceof File) {
065            fileLoader.closeTemplateSource(templateSource);
066        } else { // templateSource instanceof URLTemplateSource (not a public class)
067            urlLoader.closeTemplateSource(templateSource);
068        }
069    }
070
071    @Override
072    public Object findTemplateSource(String name) throws IOException {
073        if (name.startsWith("fs://")) { // hack for absolute paths - see
074                                        // FreemarkerEngine#render()
075            name = name.substring(5);
076        } else if (name.contains(":/")) {
077            return urlLoader.findTemplateSource(name);
078        }
079        Object obj = fileLoader.findTemplateSource(name);
080        if (obj != null) {
081            return obj;
082        }
083        return urlLoader.findTemplateSource(name);
084    }
085
086    @Override
087    public long getLastModified(Object templateSource) {
088        if (templateSource instanceof File) {
089            return fileLoader.getLastModified(templateSource);
090        } else {
091            return urlLoader.getLastModified(templateSource);
092        }
093    }
094
095    @Override
096    public Reader getReader(Object templateSource, String encoding) throws IOException {
097        if (templateSource instanceof File) {
098            return fileLoader.getReader(templateSource, encoding);
099        } else {
100            return urlLoader.getReader(templateSource, encoding);
101        }
102    }
103
104    class MyURLTemplateLoader extends URLTemplateLoader {
105        @Override
106        protected URL getURL(String arg0) {
107            if (locator != null) {
108                return locator.getResourceURL(arg0);
109            }
110            try {
111                return new URL(arg0);
112            } catch (MalformedURLException e) {
113                return null;
114            }
115        }
116    }
117
118    class MyFileTemplateLoader implements TemplateLoader {
119        @Override
120        public void closeTemplateSource(Object templateSource) throws IOException {
121            // do nothing
122        }
123
124        @Override
125        public Object findTemplateSource(String name) throws IOException {
126            if (locator != null) {
127                File file = locator.getResourceFile(name);
128                if (file != null) {
129                    return file.getCanonicalFile();
130                }
131            }
132            try {
133                File file = new File(name).getCanonicalFile();
134                if (file.isFile()) {
135                    return file;
136                }
137            } catch (IOException e) {
138                return null;
139            }
140            return null;
141        }
142
143        @Override
144        public long getLastModified(Object templateSource) {
145            try {
146                return ((File) templateSource).lastModified();
147            } catch (ClassCastException e) {
148                throw new IllegalArgumentException("templateSource is a: " + templateSource.getClass().getName());
149            }
150        }
151
152        @Override
153        public Reader getReader(Object templateSource, String encoding) throws IOException {
154            try {
155                return new InputStreamReader(new FileInputStream((File) templateSource), encoding);
156            } catch (ClassCastException e) {
157                throw new IllegalArgumentException("templateSource is a: " + templateSource.getClass().getName());
158            }
159        }
160
161    }
162
163}