Skip to content

Commit

Permalink
Pebble now works within an application container. Well at least glass…
Browse files Browse the repository at this point in the history
…fish
  • Loading branch information
mbosecke committed Oct 1, 2013
1 parent e24a92b commit cac5073
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 67 deletions.
58 changes: 20 additions & 38 deletions src/main/java/com/mitchellbosecke/pebble/PebbleEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -26,7 +25,6 @@
import com.mitchellbosecke.pebble.lexer.Lexer;
import com.mitchellbosecke.pebble.lexer.LexerImpl;
import com.mitchellbosecke.pebble.lexer.TokenStream;
import com.mitchellbosecke.pebble.loader.ResourceLoader;
import com.mitchellbosecke.pebble.loader.Loader;
import com.mitchellbosecke.pebble.node.Node;
import com.mitchellbosecke.pebble.node.NodeRoot;
Expand Down Expand Up @@ -56,7 +54,6 @@ public class PebbleEngine {
private final Class<?> templateInterfaceClass;
private final Class<?> templateAbstractClass;
private final String templateClassPrefix;
private String compiledTemplateDirectory;

/*
* Templates that have already been compiled into Java
Expand All @@ -77,16 +74,9 @@ public class PebbleEngine {
private Map<String, Operator> binaryOperators;
private Map<String, Filter> filters;
private Map<String, Test> tests;


/**
* Constructor for the Pebble Engine give file system paths to templates.
*
* @param paths
* File system paths where the templates are being stored
*/
public PebbleEngine(Collection<String> templatePaths, String compiledTemplateDirectory) {
this(new ResourceLoader(templatePaths), compiledTemplateDirectory);
public PebbleEngine() {
this(null);
}

/**
Expand All @@ -95,13 +85,11 @@ public PebbleEngine(Collection<String> templatePaths, String compiledTemplateDir
* @param loader
* The template loader for this engine
*/
public PebbleEngine(Loader loader, String compiledTemplateDirectory) {
public PebbleEngine(Loader loader) {
this.setLoader(loader);
lexer = new LexerImpl(this);
parser = new ParserImpl(this);
compiler = new CompilerImpl(this);

this.compiledTemplateDirectory = compiledTemplateDirectory;

this.addExtension(new CoreExtension());

Expand All @@ -118,32 +106,33 @@ public PebbleEngine(Loader loader, String compiledTemplateDirectory) {
* @param templateName
* The name of the template to load
* @return An instance of the template that has been compiled into Java
* @throws SyntaxException
* @throws LoaderException
* @throws SyntaxException
* @throws LoaderException
*/
public PebbleTemplate loadTemplate(String templateName) throws SyntaxException, LoaderException {
String className = this.getTemplateClassName(templateName);
PebbleTemplate instance;
if (loadedTemplates.containsKey(className)) {
instance = loadedTemplates.get(className);
} else if (!requiresCompilation(templateName)) {

/* try to load class file if it has already been compiled */
// TODO
instance = null;

} else {
/* template has not been compiled, we must compile it */
String templateSource = loader.getSource(templateName);
NodeRoot root = parse(tokenize(templateSource, templateName));

String javaSource = compile(root);

// if this template has a parent, lets make sure the parent is compiled first
if(root.hasParent()){

// if this template has a parent, lets make sure the parent is
// compiled first
if (root.hasParent()) {
this.loadTemplate(root.getParentFileName());
}

instance = getCompiler().compileToJava(javaSource, className);
instance.setEngine(this);
loadedTemplates.put(className, instance);
Expand All @@ -152,7 +141,7 @@ public PebbleTemplate loadTemplate(String templateName) throws SyntaxException,
}

private boolean requiresCompilation(String templateName) {

return true;
}

Expand All @@ -165,7 +154,7 @@ private boolean requiresCompilation(String templateName) {
* @param filename
* The name of the template (used for meaningful error messages)
* @return The TokenStream which is ready for parsing
* @throws SyntaxException
* @throws SyntaxException
*/
private TokenStream tokenize(String source, String filename) throws SyntaxException {
return getLexer().tokenize(source, filename);
Expand All @@ -178,7 +167,7 @@ private TokenStream tokenize(String source, String filename) throws SyntaxExcept
* @param stream
* The TokenStream which is ready for parsing
* @return The root Node of the AST
* @throws SyntaxException
* @throws SyntaxException
*/
private NodeRoot parse(TokenStream stream) throws SyntaxException {
return getParser().parse(stream);
Expand Down Expand Up @@ -346,10 +335,11 @@ public Map<String, Test> getTests() {
* @return The final name that would be used for creating a Java class
*/
public String getTemplateClassName(String templateName) {

// if tempalteName is part of a directory path, get just the last segment

// if tempalteName is part of a directory path, get just the last
// segment
templateName = templateName.replaceFirst(".*/([^/]+).*", "$1");

String classNameHash = "";
byte[] bytesOfName;
MessageDigest md;
Expand Down Expand Up @@ -379,12 +369,4 @@ public Class<?> getTemplateInterfaceClass() {
public Class<?> getTemplateAbstractClass() {
return templateAbstractClass;
}

public String getCompiledTemplateDirectory() {
return compiledTemplateDirectory;
}

public void setCompiledTemplateDirectory(String compiledTemplateDirectory) {
this.compiledTemplateDirectory = compiledTemplateDirectory;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,18 @@ public static ClassFileManager getInstance(StandardJavaFileManager manager) {
@Override
public ClassLoader getClassLoader(Location location) {

return new SecureClassLoader() {
return new SecureClassLoader(ClassFileManager.class.getClassLoader()) {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] b = classObjects.get(name).getBytes();
return super.defineClass(name, b, 0, b.length);
ByteArrayJavaFileObject classObject = classObjects.get(name);

if (classObject == null) {
return super.loadClass(name);
} else {
byte[] b = classObject.getBytes();
return super.defineClass(name, b, 0, b.length);
}

}
};
}
Expand Down Expand Up @@ -84,10 +91,9 @@ public Iterable<JavaFileObject> list(Location location, String packageName, Set<
public String inferBinaryName(Location location, JavaFileObject file) {
if (file instanceof ByteArrayJavaFileObject) {
return ((ByteArrayJavaFileObject) file).getBinaryName();
} else {
} else {
return fileManager.inferBinaryName(location, file);
}
}


}
37 changes: 22 additions & 15 deletions src/main/java/com/mitchellbosecke/pebble/compiler/CompilerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
******************************************************************************/
package com.mitchellbosecke.pebble.compiler;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

Expand Down Expand Up @@ -147,13 +150,22 @@ public PebbleTemplate compileToJava(String javaSource, String className) {
List<JavaFileObject> compilationUnits = new ArrayList<>();
compilationUnits.add(new StringSourceFileObject(fullClassName, javaSource));

/* Prepare any compilation options to be used during compilation */
// compiledTemplatesPath = compiledTemplatesPath.replace(" ", "\\ ");
// prepare compilation options
List<String> compilationOptions = new ArrayList<>();

// logger.info(String.format("Compiling to %s", compiledTemplatesPath));
// String[] compileOptions = new String[] { "-d", compiledTemplatesPath
// };
// Iterable<String> compilationOptions = Arrays.asList(compileOptions);
// build classpath
StringBuilder sb = new StringBuilder();

try {
sb.append(System.getProperty("java.class.path")).append(File.pathSeparator)
.append(PebbleTemplate.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
} catch (URISyntaxException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

String classpath = sb.toString();
compilationOptions.addAll(Arrays.asList("-classpath", classpath));

/* Create a diagnostic controller, which holds the compilation problems */
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
Expand All @@ -162,7 +174,8 @@ public PebbleTemplate compileToJava(String javaSource, String className) {
* Create a compilation task from compiler by passing in the required
* input objects prepared above
*/
CompilationTask compilerTask = compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits);
CompilationTask compilerTask = compiler.getTask(null, fileManager, diagnostics, compilationOptions, null,
compilationUnits);

// Perform the compilation by calling the call method on compilerTask
// object.
Expand All @@ -181,14 +194,8 @@ public PebbleTemplate compileToJava(String javaSource, String className) {
}

try {

// PebbleClassLoader pebbleClassLoader =
// PebbleClassLoader.getInstance();
// pebbleClassLoader.register(fullClassName,
// fileManager.getCompiledJavaClassObject());

AbstractPebbleTemplate template = (AbstractPebbleTemplate) fileManager.getClassLoader(null)
.loadClass(fullClassName).newInstance();
ClassLoader cl = fileManager.getClassLoader(null);
AbstractPebbleTemplate template = (AbstractPebbleTemplate) cl.loadClass(fullClassName).newInstance();
template.setSourceCode(getSource());
return template;
} catch (IllegalAccessException | InstantiationException e) {
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/com/mitchellbosecke/pebble/loader/Loader.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@
******************************************************************************/
package com.mitchellbosecke.pebble.loader;

import java.util.Date;

import com.mitchellbosecke.pebble.error.LoaderException;


public interface Loader {

public String getSource(String templateName) throws LoaderException;

//boolean isFresh(String templateName, Date timestamp) throws LoaderException;
public void setPrefix(String prefix);

public void setSuffix(String suffix);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*******************************************************************************
* This file is part of Pebble.
*
* Copyright (c) 2012 Mitchell Bosecke.
*
* This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
* Unported License. To view a copy of this license, visit
* http://creativecommons.org/licenses/by-sa/3.0/
******************************************************************************/
package com.mitchellbosecke.pebble.loader;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mitchellbosecke.pebble.error.LoaderException;

public class PebbleDefaultLoader implements Loader {

private static final Logger logger = LoggerFactory.getLogger(PebbleDefaultLoader.class);

private String prefix;

private String suffix;

private Map<String, Reader> readerCache = new HashMap<>();

@Override
public String getSource(String templateName) throws LoaderException {
Reader location = getReader(templateName);
String source = null;

try {
source = IOUtils.toString(location);
} catch (IOException e) {
throw new LoaderException("Template can not be found.");
}
return source;
}

protected Reader getReader(String templateName) throws LoaderException {

Reader reader = readerCache.containsKey(templateName) ? readerCache.get(templateName) : null;

if (reader == null) {
InputStream is = null;

String path = getPrefix().endsWith(String.valueOf(File.separatorChar)) ? getPrefix() : getPrefix()
+ File.separatorChar;

String location = path + templateName + (getSuffix() == null ? "" : getSuffix());
logger.info("Looking for template in {}.", location);

// try ContextClassLoader
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
is = ccl.getResourceAsStream(location);

// try ResourceLoader's class loader
ClassLoader rcl = PebbleDefaultLoader.class.getClassLoader();
if (is == null) {
is = rcl.getResourceAsStream(location);
}

// try to load File
if (is == null) {
File file = new File(path, templateName);
if (file.exists() && file.isFile()) {
try {
is = new FileInputStream(file);
} catch (FileNotFoundException e) {
// TODO: throw exception?
}
}
}

if (is == null) {
throw new LoaderException("Could not find template \"" + templateName + "\"");
}

try {
reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
} catch (UnsupportedEncodingException e) {
}
}

readerCache.put(templateName, reader);

return reader;
}

public String getSuffix() {
return suffix;
}

public void setSuffix(String suffix) {
this.suffix = suffix;
}

public String getPrefix() {
return prefix;
}

public void setPrefix(String prefix) {
this.prefix = prefix;
}

}
Loading

0 comments on commit cac5073

Please sign in to comment.