manipulação razoável de ScriptException lançada pelo rinoceronte JSR223

Estou começando a me deparar com os pequenos segredos sujos do que é um ambiente de script JSR223 muito útil.

Eu estou usando a versão embutida do Rhino enviada com o Java 6 SE, acessando-a através do ScriptingEngine et al de JSR223.

Quando recebo uma exceção causada por um object Java que eu exportei para o ambiente Javascript, é uma ScriptingException que envolve uma sun.org.mozilla.javascript.internal.WrappedException que envolve minha exceção real (por exemplo, UnsupportedOperationException ou qualquer outra coisa)

O ScriptingException retorna nulo para getFileName () e -1 para getLineNumber (). Mas quando eu olho para a mensagem e para o depurador, o WrappedException tem o nome do arquivo e o número da linha corretos, não é apenas publicá-lo por meio dos methods getter do ScriptingException.

Ótimo. Agora o que eu faço? Eu não sei como vou usar sun.org.mozilla.javascript.internal.wrappedException que não é uma class pública de qualquer maneira.

Argh. O Rhino do Java 6 faz a mesma coisa (não publica o nome do arquivo / número de linha / etc através dos methods do ScriptingException) com sun.org.mozilla.javascript.internal.EvaluatorException e quem sabe quantas outras exceções.

A única maneira razoável que consigo pensar para lidar com isso é usar reflection. Aqui está minha solução.

 void handleScriptingException(ScriptingException se) { final Throwable t1 = se.getCause(); String lineSource = null; String filename = null; Integer lineNumber = null; if (hasGetterMethod(t1, "sourceName")) { lineNumber = getProperty(t1, "lineNumber", Integer.class); filename = getProperty(t1, "sourceName", String.class); lineSource = getProperty(t1, "lineSource", String.class); } else { filename = se.getFileName(); lineNumber = se.getLineNumber(); } /* do something with this info */ } static private Method getGetterMethod(Object object, String propertyName) { String methodName = "get"+getBeanSuffix(propertyName); try { Class cl = object.getClass(); return cl.getMethod(methodName); } catch (NoSuchMethodException e) { return null; /* gulp */ } } static private String getBeanSuffix(String propertyName) { return propertyName.substring(0,1).toUpperCase() +propertyName.substring(1); } static private boolean hasGetterMethod(Object object, String propertyName) { return getGetterMethod(object, propertyName) != null; } static private  T getProperty(Object object, String propertyName, Class cl) { try { Object result = getGetterMethod(object, propertyName).invoke(object); return cl.cast(result); } catch (Exception e) { e.printStackTrace(); } return null; }