I wrote this small web interface to dynamically communicate with Hibernate Statistics implementation (in case you don't have JMX :-). It uses BeanShell (www.beanshell.org) to interpret [Interpreter API] our commands from web interface.
In web action (getting content from request):
String content = request.getParameter("content");
ByteArrayOutputStream out = new ByteArrayOutputStream();
OutputStream err =
new LoggerOutputStream(LogFactory.getLog(interpreterViewer.getClass()),
Priority.ERROR_INT);
InterpreterViewer interpreterViewer = new StatisticsInterpreterViewer();
try {
interpreterViewer.interpret(content, outputs, out, err);
} finally {
out.close();
err.close();
}
String output = new String(out.toByteArray());
interpreter vewier interface
public interface InterpreterViewer {
public void interpret(String content, Map outputs,
OutputStream out, OutputStream err);
}
base abstract class for simple interpreter viewers
public abstract class AbstractInterpreterViewer implements InterpreterViewer {
protected MapInterpreter createInterpreter(Map outputs,
OutputStream out, OutputStream err) {
return new MapInterpreter(outputs, null, new PrintStream(out),
new PrintStream(err), false);
}
public void interpret(String content, Map outputs, OutputStream out, OutputStream err) {
try {
MapInterpreter interpreter = createInterpreter(outputs ,out, err);
prepareInterpreter(interpreter);
InterpreterCommand[] commands = parserContent(content);
for (int i = 0; i < commands.length; i++) {
commands[i].execute(interpreter);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//override
protected void prepareInterpreter(Interpreter interpreter) throws EvalError {
};
protected InterpreterCommand[] parserContent(String content) throws IOException {
BufferedReader reader = new BufferedReader(new StringReader(content));
List commandList = new ArrayList();
String line = null;
while((line = reader.readLine()) != null) {
int p1 = line.indexOf('[');
int p2 = line.indexOf(']');
if (p1 >= 0 && p2 > 0) {
String command = line.substring(p1 + 1, p2);
String value = line.substring(p2 + 1).trim();
commandList.add(new InterpreterCommand(command, value));
}
}
return (InterpreterCommand[])commandList.toArray(
new InterpreterCommand[commandList.size()]);
}
}
command - takes the form of [cmd] value
public class InterpreterCommand {
public static final String LINE_BREAK = "LINE_BREAK";
private static final String PRINT = "print";
private static final String GET = "get";
private static final String SET = "set";
private static final String EVAL = "eval";
private static final String UNSET = "unset";
private String command;
private String value;
public InterpreterCommand(String command, String value) {
this.command = command;
this.value = value;
}
public void execute(MapInterpreter interpreter) throws EvalError {
if (PRINT.equalsIgnoreCase(command)) {
doPrint(interpreter);
} else if (GET.equalsIgnoreCase(command)) {
doGet(interpreter);
} else if (SET.equalsIgnoreCase(command)) {
doSet(interpreter);
} else if (EVAL.equalsIgnoreCase(command)) {
doEval(interpreter);
} else if (UNSET.equalsIgnoreCase(command)) {
doUnset(interpreter);
} else {
throw new IllegalArgumentException("No such command: " + command);
}
}
protected void doUnset(MapInterpreter interpreter) throws EvalError {
interpreter.unset(value);
}
protected void doEval(MapInterpreter interpreter) throws EvalError {
interpreter.eval(value);
}
protected void doSet(MapInterpreter interpreter) throws EvalError {
Object object = interpreter.getObject(value);
interpreter.set(value, object);
}
protected void doGet(MapInterpreter interpreter) throws EvalError {
interpreter.setObject(value, interpreter.get(value));
}
protected void doPrint(MapInterpreter interpreter) throws EvalError {
String tempName = "temp" + interpreter.getCount();
interpreter.eval(tempName + " = " + value);
Object object = interpreter.get(tempName);
PrintStream out = interpreter.getOut();
out.println("[" + value + "] " + renderObject(object));
Object lineBreak = interpreter.getOutput(LINE_BREAK);
if (lineBreak != null) {
out.print(lineBreak);
}
interpreter.unset(tempName);
}
private String renderObject(Object object) {
if (object.getClass().isArray()) {
return StringUtils.arrayToCommaDelimitedString((Object[])object);
} else {
return object.toString();
}
}
}
just an extension to hold new objects and output rendering details
public class MapInterpreter extends Interpreter {
private Map objects = new HashMap();
private Map outputs = new HashMap();
private int counter = 0;
public MapInterpreter(Reader reader,
PrintStream out,
PrintStream err,
boolean b) {
this(null, reader, out, err, b);
}
public MapInterpreter(Map outputs, Reader reader,
PrintStream out,
PrintStream err,
boolean b) {
super(reader, out, err, b);
if (outputs != null) {
this.outputs = outputs;
}
}
public void setObject(String name, Object object) {
objects.put(name, object);
}
public Object getObject(String name) {
return objects.get(name);
}
public Object getOutput(String key) {
return outputs.get(key);
}
public int getCount() {
return counter++;
}
}
Just put sessionFactory and its statistics into interpreter's variables to be able to use them later.
public class StatisticsInterpreterViewer extends AbstractInterpreterViewer
implements InterpreterViewer {
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
protected void prepareInterpreter(Interpreter interpreter) throws EvalError {
interpreter.set("sf", getSessionFactory());
interpreter.set("stats", getSessionFactory().getStatistics());
}
}
So then in web interface you write something like this:
[print] stats.getSessionCloseCount()
And you should receive (ok, your number :-):
[stats.getSessionCloseCount()] 5
Rgds, Ales
Comments