package bsh.servlet;
/**
This file is derived from Pat Niemeyer's free utilities package.
Now part of BeanShell.
@see http://www.pat.net/javautil/
@version 1.0
@author Pat Niemeyer (pat@pat.net)
*/
import java.io.*;
import java.util.*;
import java.net.
URL;
/**
This is a simple template engine. An instance of SimpleTemplate wraps
a StringBuffer and performs replace operations on one or more parameters
embedded as HMTL style comments. The value can then be retrieved as a
String or written to a stream.
Template values in the text are of the form:
<!-- TEMPLATE-NAME -->
Substitutions then take the form of:
template.replace( "NAME", value );
Two static util methods are provided to help read the text of a template
from a stream (perhaps a URL or resource). e.g.
@author Pat Niemeyer
*/
public class
SimpleTemplate
{
StringBuffer buff;
static
String NO_TEMPLATE = "NO_TEMPLATE"; // Flag for non-existent
static
Map templateData = new
HashMap();
static boolean
cacheTemplates = true;
/**
Get a template by name, with caching.
Note: this should be updated to search the resource path first, etc.
Create a new instance of a template from the specified file.
The file text is cached so lookup is fast. Failure to find the
file is also cached so the read will not happen twice.
*/
public static
SimpleTemplate getTemplate(
String file )
{
String templateText = (
String)
templateData.
get(
file );
if (
templateText == null || !
cacheTemplates ) {
try {
FileReader fr = new
FileReader(
file );
templateText =
SimpleTemplate.
getStringFromStream(
fr );
templateData.
put(
file,
templateText );
} catch (
IOException e ) {
// Not found
templateData.
put(
file,
NO_TEMPLATE );
}
} else
// Quick check prevents trying each time
if (
templateText.
equals(
NO_TEMPLATE ) )
return null;
if (
templateText == null )
return null;
else
return new
SimpleTemplate(
templateText );
}
public static
String getStringFromStream(
InputStream ins )
throws
IOException
{
return
getStringFromStream( new
InputStreamReader(
ins ) );
}
public static
String getStringFromStream(
Reader reader ) throws
IOException {
StringBuffer sb = new
StringBuffer();
BufferedReader br = new
BufferedReader(
reader );
String line;
while ( (
line =
br.
readLine() ) != null )
sb.
append(
line +"\n");
return
sb.
toString();
}
public
SimpleTemplate(
String template ) {
init(
template);
}
public
SimpleTemplate(
Reader reader ) throws
IOException {
String template =
getStringFromStream(
reader );
init(
template);
}
public
SimpleTemplate(
URL url ) throws
IOException
{
String template =
getStringFromStream(
url.
openStream() );
init(
template);
}
private void
init(
String s ) {
buff = new
StringBuffer(
s );
}
/**
Substitute the specified text for the parameter
*/
public void
replace(
String param,
String value ) {
int []
range;
while ( (
range =
findTemplate(
param )) != null )
buff.
replace(
range[0],
range[1],
value );
}
/**
Find the starting (inclusive) and ending (exclusive) index of the
named template and return them as a two element int [].
Or return null if the param is not found.
*/
int []
findTemplate(
String name ) {
String text =
buff.
toString();
int
len =
text.
length();
int
start = 0;
while (
start <
len ) {
// Find begin and end comment
int
cstart =
text.
indexOf( "<!--",
start );
if (
cstart == -1 )
return null; // no more comments
int
cend =
text.
indexOf( "-->",
cstart );
if (
cend == -1 )
return null; // no more complete comments
cend += "-->".
length();
// Find template tag
int
tstart =
text.
indexOf( "TEMPLATE-",
cstart );
if (
tstart == -1 ) {
start =
cend; // try the next comment
continue;
}
// Is the tag inside the comment we found?
if (
tstart >
cend ) {
start =
cend; // try the next comment
continue;
}
// find begin and end of param name
int
pstart =
tstart + "TEMPLATE-".
length();
int
pend =
len;
for (
pend =
pstart;
pend <
len;
pend++) {
char
c =
text.
charAt(
pend );
if (
c == ' ' ||
c == '\t' ||
c == '-' )
break;
}
if (
pend >=
len )
return null;
String param =
text.
substring(
pstart,
pend );
// If it's the correct one, return the comment extent
if (
param.
equals(
name ) )
return new int [] {
cstart,
cend };
//System.out.println( "Found param: {"+param+"} in comment: "+ text.substring(cstart, cend) +"}");
// Else try the next one
start =
cend;
}
// Not found
return null;
}
public
String toString() {
return
buff.
toString();
}
public void
write(
PrintWriter out ) {
out.
println(
toString() );
}
public void
write(
PrintStream out ) {
out.
println(
toString() );
}
/**
usage: filename param value
*/
public static void
main(
String []
args ) throws
IOException
{
String filename =
args[0];
String param =
args[1];
String value =
args[2];
FileReader fr = new
FileReader(
filename );
String templateText =
SimpleTemplate.
getStringFromStream(
fr );
SimpleTemplate template = new
SimpleTemplate(
templateText );
template.
replace(
param,
value );
template.
write(
System.
out );
}
public static void
setCacheTemplates( boolean
b ) {
cacheTemplates =
b;
}
}