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