Anonymous avatar Anonymous committed ac47364

Refactoring template loading

Comments (0)

Files changed (5)

chempound-webapp/src/main/java/net/chempound/webapp/DefaultChempoundWebModule.java

 import net.chempound.webapp.plugins.PluginRegistry;
 import net.chempound.webapp.plugins.SkinRegistry;
 import net.chempound.webapp.sword.impl.SwordModule;
+import net.chempound.webapp.template.DefaultFreemarkerService;
 import org.restlet.Application;
 import org.restlet.Component;
 import org.restlet.Context;

chempound-webapp/src/main/java/net/chempound/webapp/DefaultFreemarkerService.java

-package net.chempound.webapp;
-
-import freemarker.cache.FileTemplateLoader;
-import freemarker.cache.StatefulTemplateLoader;
-import freemarker.cache.TemplateLoader;
-import freemarker.template.*;
-import net.chempound.config.BaseUri;
-import net.chempound.config.ChempoundConfiguration;
-import net.chempound.services.FreemarkerService;
-import net.chempound.webapp.plugins.CssRegistry;
-import org.apache.commons.io.FileUtils;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import java.io.File;
-import java.io.IOException;
-import java.io.Reader;
-import java.net.URI;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author sea36
- */
-@Singleton
-public class DefaultFreemarkerService implements FreemarkerService {
-
-    private final Configuration freemarker;
-    private final File templateRoot;
-    private final PluginTemplateRouter templateLoader;
-    private final CssRegistry cssRegistry;
-
-    @Inject
-    public DefaultFreemarkerService(final ChempoundConfiguration configuration, final GlobalData macroService, @BaseUri final URI baseUri, final CssRegistry cssRegistry) throws TemplateModelException, IOException {
-        this.cssRegistry = cssRegistry;
-        this.templateRoot = new File(configuration.getWorkspace(), "cache/templates");
-
-        this.freemarker = new Configuration();
-        this.freemarker.setWhitespaceStripping(true);
-        this.freemarker.setOutputEncoding("UTF-8");
-        this.freemarker.addAutoImport("macro", "/include/macros.ftl");
-        this.freemarker.addAutoImport("layout", "/include/layout.ftl");
-        String uri = baseUri.toString();
-        if (uri.endsWith("/")) {
-            uri = uri.substring(0, uri.length() - 1);
-        }
-        this.freemarker.setSharedVariable("URI_BASE", uri);
-        this.freemarker.setSharedVariable("CHEMPOUND", macroService);
-        this.freemarker.setSharedVariable("@", macroService);
-        this.freemarker.setNumberFormat("0.######");
-        this.freemarker.setSharedVariable("STYLESHEETS", new TemplateSequenceModel() {
-            @Override
-            public TemplateModel get(final int index) throws TemplateModelException {
-                return new SimpleScalar(cssRegistry.get(index));
-            }
-
-            @Override
-            public int size() throws TemplateModelException {
-                return cssRegistry.size();
-            }
-        });
-
-        final FileTemplateLoader defaultLoader = getDefaultTemplateLoader();
-        this.templateLoader = new PluginTemplateRouter(defaultLoader);
-        this.freemarker.setTemplateLoader(templateLoader);
-    }
-
-    private FileTemplateLoader getDefaultTemplateLoader() throws IOException {
-        final File templateDir = getDefaultTemplateDir();
-        FileExtractor.extract(DefaultFreemarkerService.class, "/net/chempound/templates/", templateDir);
-        return new FileTemplateLoader(templateDir);
-    }
-
-    private File getDefaultTemplateDir() throws IOException {
-        final File templateDir = new File(templateRoot, "default");
-        FileUtils.forceMkdir(templateDir);
-        return templateDir;
-    }
-
-    public Template getTemplate(final String name) throws IOException {
-        return freemarker.getTemplate(name);
-    }
-
-    public void registerPlugin(final String name, final Class<?> context, final String path) throws IOException {
-        final File templateDir = getPluginTemplateDir(name);
-        FileExtractor.extract(context, path, templateDir);
-        templateLoader.addPlugin(name, new FileTemplateLoader(templateDir));
-    }
-
-    public void registerSkin(final String name, final Class<?> context, final String path) throws IOException {
-        final File templateDir = getSkinTemplateDir(name);
-        FileExtractor.extract(context, path, templateDir);
-        templateLoader.addPlugin(name, new FileTemplateLoader(templateDir));
-    }
-
-    private File getPluginTemplateDir(final String name) throws IOException {
-        final File templateDir = new File(templateRoot, "plugins/" + name);
-        FileUtils.forceMkdir(templateDir);
-        return templateDir;
-    }
-
-    private File getSkinTemplateDir(final String name) throws IOException {
-        final File templateDir = new File(templateRoot, "skins/" + name);
-        FileUtils.forceMkdir(templateDir);
-        return templateDir;
-    }
-
-    // Based on freemarker multiloader
-    private static class PluginTemplateRouter implements StatefulTemplateLoader {
-
-        private final Map<String,TemplateLoader> lastLoaderForName = Collections.synchronizedMap(new HashMap<String,TemplateLoader>());
-        private final TemplateLoader defaultLoader;
-        private final Map<String,TemplateLoader> loaderMap = Collections.synchronizedMap(new HashMap<String,TemplateLoader>());
-
-        public PluginTemplateRouter(final TemplateLoader defaultLoader) throws IOException {
-            this.defaultLoader = defaultLoader;
-        }
-
-        public Object findTemplateSource(final String name) throws IOException {
-
-            final String fullname = name;
-
-            // Use soft affinity - give the loader that last found this
-            // resource a chance to find it again first.
-            final TemplateLoader lastLoader = lastLoaderForName.get(name);
-            if (lastLoader != null) {
-                final Object source = lastLoader.findTemplateSource(name);
-                if (source != null) {
-                    return new MultiSource(source, lastLoader);
-                }
-            }
-
-            final TemplateLoader loader;
-
-            if (name.startsWith("plugins/")) {
-                final int i = name.indexOf('/', 8);
-                final String plugin = name.substring(8, i);
-                loader = loaderMap.get(plugin);
-                return findTemplateSource(loader, name.substring(i + 1), fullname);
-            } else if (name.startsWith("skins/")) {
-                final int i = name.indexOf('/', 6);
-                final String plugin = name.substring(6, i);
-                loader = loaderMap.get(plugin);
-                return findTemplateSource(loader, name.substring(i + 1), fullname);
-            } else {
-                return findTemplateSource(defaultLoader, name, fullname);
-            }
-        }
-        
-        private Object findTemplateSource(final TemplateLoader loader, final String name, final String fullname) throws IOException {
-            if (loader != null) {
-                final Object source = loader.findTemplateSource(name);
-                if (source != null) {
-                    if (source != null) {
-                        lastLoaderForName.put(fullname, loader);
-                        return new MultiSource(source, loader);
-                    }
-                }
-            }
-
-            lastLoaderForName.remove(fullname);
-            // Resource not found
-            return null;
-        }
-
-        public long getLastModified(final Object templateSource) {
-            return ((MultiSource)templateSource).getLastModified();
-        }
-
-        public Reader getReader(final Object templateSource, final String encoding) throws IOException {
-            return ((MultiSource)templateSource).getReader(encoding);
-        }
-
-        public void closeTemplateSource(final Object templateSource) throws IOException {
-            ((MultiSource)templateSource).close();
-        }
-
-        public void resetState() {
-            lastLoaderForName.clear();
-            if (defaultLoader instanceof StatefulTemplateLoader) {
-
-            }
-            for (final TemplateLoader loader : loaderMap.values()) {
-                if (loader instanceof StatefulTemplateLoader) {
-                    ((StatefulTemplateLoader)loader).resetState();
-                }
-            }
-        }
-
-        void addPlugin(final String plugin, final TemplateLoader loader) {
-            loaderMap.put(plugin, loader);
-        }
-
-        /**
-         * Represents a template source bound to a specific template loader. It
-         * serves as the complete template source descriptor used by the
-         * MultiTemplateLoader class.
-         */
-        private static final class MultiSource {
-
-            private final Object source;
-            private final TemplateLoader loader;
-
-            MultiSource(final Object source, final TemplateLoader loader)  {
-                this.source = source;
-                this.loader = loader;
-            }
-
-            long getLastModified() {
-                return loader.getLastModified(source);
-            }
-
-            Reader getReader(final String encoding) throws IOException {
-                return loader.getReader(source, encoding);
-            }
-
-            void close() throws IOException {
-                loader.closeTemplateSource(source);
-            }
-
-            public boolean equals(final Object o) {
-                if (o instanceof MultiSource) {
-                    final MultiSource m = (MultiSource)o;
-                    return m.loader.equals(loader) && m.source.equals(source);
-                }
-                return false;
-            }
-
-            public int hashCode() {
-                return loader.hashCode() + 31 * source.hashCode();
-            }
-
-            public String toString() {
-                return source.toString();
-            }
-        }
-
-    }
-
-}

chempound-webapp/src/main/java/net/chempound/webapp/template/DefaultFreemarkerService.java

+package net.chempound.webapp.template;
+
+import freemarker.cache.FileTemplateLoader;
+import freemarker.template.*;
+import net.chempound.config.BaseUri;
+import net.chempound.config.ChempoundConfiguration;
+import net.chempound.services.FreemarkerService;
+import net.chempound.webapp.FileExtractor;
+import net.chempound.webapp.GlobalData;
+import net.chempound.webapp.plugins.CssRegistry;
+import org.apache.commons.io.FileUtils;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+
+/**
+ * @author sea36
+ */
+@Singleton
+public class DefaultFreemarkerService implements FreemarkerService {
+
+    private final Configuration freemarker;
+    private final File templateRoot;
+    private final RoutingTemplateLoader templateLoader;
+    private final CssRegistry cssRegistry;
+
+    @Inject
+    public DefaultFreemarkerService(final ChempoundConfiguration configuration, final GlobalData macroService, @BaseUri final URI baseUri, final CssRegistry cssRegistry) throws TemplateModelException, IOException {
+        this.cssRegistry = cssRegistry;
+        this.templateRoot = new File(configuration.getWorkspace(), "cache/templates");
+
+        this.freemarker = new Configuration();
+        this.freemarker.setWhitespaceStripping(true);
+        this.freemarker.setOutputEncoding("UTF-8");
+        this.freemarker.addAutoImport("macro", "/include/macros.ftl");
+        this.freemarker.addAutoImport("layout", "/include/layout.ftl");
+        String uri = baseUri.toString();
+        if (uri.endsWith("/")) {
+            uri = uri.substring(0, uri.length() - 1);
+        }
+        this.freemarker.setSharedVariable("URI_BASE", uri);
+        this.freemarker.setSharedVariable("CHEMPOUND", macroService);
+        this.freemarker.setSharedVariable("@", macroService);
+        this.freemarker.setNumberFormat("0.######");
+        this.freemarker.setSharedVariable("STYLESHEETS", new TemplateSequenceModel() {
+            @Override
+            public TemplateModel get(final int index) throws TemplateModelException {
+                return new SimpleScalar(cssRegistry.get(index));
+            }
+
+            @Override
+            public int size() throws TemplateModelException {
+                return cssRegistry.size();
+            }
+        });
+
+        final FileTemplateLoader defaultLoader = getDefaultTemplateLoader();
+        this.templateLoader = new RoutingTemplateLoader(defaultLoader);
+        this.freemarker.setTemplateLoader(templateLoader);
+    }
+
+    private FileTemplateLoader getDefaultTemplateLoader() throws IOException {
+        final File templateDir = getDefaultTemplateDir();
+        FileExtractor.extract(DefaultFreemarkerService.class, "/net/chempound/templates/", templateDir);
+        return new FileTemplateLoader(templateDir);
+    }
+
+    private File getDefaultTemplateDir() throws IOException {
+        final File templateDir = new File(templateRoot, "default");
+        FileUtils.forceMkdir(templateDir);
+        return templateDir;
+    }
+
+    public Template getTemplate(final String name) throws IOException {
+        return freemarker.getTemplate(name);
+    }
+
+    public void registerPlugin(final String name, final Class<?> context, final String path) throws IOException {
+        final File templateDir = getPluginTemplateDir(name);
+        FileExtractor.extract(context, path, templateDir);
+        templateLoader.addPlugin(name, new FileTemplateLoader(templateDir));
+    }
+
+    public void registerSkin(final String name, final Class<?> context, final String path) throws IOException {
+        final File templateDir = getSkinTemplateDir(name);
+        FileExtractor.extract(context, path, templateDir);
+        templateLoader.addPlugin(name, new FileTemplateLoader(templateDir));
+    }
+
+    private File getPluginTemplateDir(final String name) throws IOException {
+        final File templateDir = new File(templateRoot, "plugins/" + name);
+        FileUtils.forceMkdir(templateDir);
+        return templateDir;
+    }
+
+    private File getSkinTemplateDir(final String name) throws IOException {
+        final File templateDir = new File(templateRoot, "skins/" + name);
+        FileUtils.forceMkdir(templateDir);
+        return templateDir;
+    }
+}

chempound-webapp/src/main/java/net/chempound/webapp/template/MultiSource.java

+package net.chempound.webapp.template;
+
+import freemarker.cache.TemplateLoader;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * Represents a template source bound to a specific template loader. It
+ * serves as the complete template source descriptor used by the
+ * MultiTemplateLoader class.
+ */
+final class MultiSource {
+
+    private final Object source;
+    private final TemplateLoader loader;
+
+    MultiSource(final Object source, final TemplateLoader loader)  {
+        this.source = source;
+        this.loader = loader;
+    }
+
+    long getLastModified() {
+        return loader.getLastModified(source);
+    }
+
+    Reader getReader(final String encoding) throws IOException {
+        return loader.getReader(source, encoding);
+    }
+
+    void close() throws IOException {
+        loader.closeTemplateSource(source);
+    }
+
+    public boolean equals(final Object o) {
+        if (o instanceof MultiSource) {
+            final MultiSource m = (MultiSource)o;
+            return m.loader.equals(loader) && m.source.equals(source);
+        }
+        return false;
+    }
+
+    public int hashCode() {
+        return loader.hashCode() + 31 * source.hashCode();
+    }
+
+    public String toString() {
+        return source.toString();
+    }
+}

chempound-webapp/src/main/java/net/chempound/webapp/template/RoutingTemplateLoader.java

+package net.chempound.webapp.template;
+
+import freemarker.cache.StatefulTemplateLoader;
+import freemarker.cache.TemplateLoader;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+// Based on freemarker multiloader
+class RoutingTemplateLoader implements StatefulTemplateLoader {
+
+    private final Map<String,TemplateLoader> lastLoaderForName = Collections.synchronizedMap(new HashMap<String, TemplateLoader>());
+    private final TemplateLoader defaultLoader;
+    private final Map<String,TemplateLoader> loaderMap = Collections.synchronizedMap(new HashMap<String,TemplateLoader>());
+
+    public RoutingTemplateLoader(final TemplateLoader defaultLoader) throws IOException {
+        this.defaultLoader = defaultLoader;
+    }
+
+    @Override
+    public Object findTemplateSource(final String name) throws IOException {
+
+        // Use soft affinity - give the loader that last found this
+        // resource a chance to find it again first.
+        final TemplateLoader lastLoader = lastLoaderForName.get(name);
+        if (lastLoader != null) {
+            final Object source = lastLoader.findTemplateSource(name);
+            if (source != null) {
+                return new MultiSource(source, lastLoader);
+            }
+        }
+
+        final TemplateLoader loader;
+
+        if (name.startsWith("plugins/")) {
+            final int i = name.indexOf('/', 8);
+            final String plugin = name.substring(8, i);
+            loader = loaderMap.get(plugin);
+            return findTemplateSource(loader, name.substring(i + 1), name);
+        } else if (name.startsWith("skins/")) {
+            final int i = name.indexOf('/', 6);
+            final String plugin = name.substring(6, i);
+            loader = loaderMap.get(plugin);
+            return findTemplateSource(loader, name.substring(i + 1), name);
+        } else {
+            return findTemplateSource(defaultLoader, name, name);
+        }
+    }
+
+    private Object findTemplateSource(final TemplateLoader loader, final String name, final String fullname) throws IOException {
+        if (loader != null) {
+            final Object source = loader.findTemplateSource(name);
+            if (source != null) {
+                if (source != null) {
+                    lastLoaderForName.put(fullname, loader);
+                    return new MultiSource(source, loader);
+                }
+            }
+        }
+
+        lastLoaderForName.remove(fullname);
+        // Resource not found
+        return null;
+    }
+
+    @Override
+    public long getLastModified(final Object templateSource) {
+        return ((MultiSource)templateSource).getLastModified();
+    }
+
+    @Override
+    public Reader getReader(final Object templateSource, final String encoding) throws IOException {
+        return ((MultiSource)templateSource).getReader(encoding);
+    }
+
+    @Override
+    public void closeTemplateSource(final Object templateSource) throws IOException {
+        ((MultiSource)templateSource).close();
+    }
+
+    @Override
+    public void resetState() {
+        lastLoaderForName.clear();
+        if (defaultLoader instanceof StatefulTemplateLoader) {
+
+        }
+        for (final TemplateLoader loader : loaderMap.values()) {
+            if (loader instanceof StatefulTemplateLoader) {
+                ((StatefulTemplateLoader)loader).resetState();
+            }
+        }
+    }
+
+    void addPlugin(final String plugin, final TemplateLoader loader) {
+        loaderMap.put(plugin, loader);
+    }
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.