2011-04-05 52 views
7

我開始遇到什麼是非常有用的JSR223腳本環境的骯髒小祕密。合理處理由JSR223拋出的ScriptException犀牛

我使用Java 6 SE附帶的內置版Rhino,通過JSR223的ScriptingEngine等訪問它。

當我造成的,我出口到JavaScript環境的Java對象的例外,它是一個ScriptingException一個包裝了sun.org.mozilla.javascript.internal.WrappedException一個封裝我真正的例外(如UnsupportedOperationException或其他)

ScriptingException返回空getFileName()和getLineNumber()的-1。 但是當我看着消息和調試器時,WrappedException具有正確的文件名和行號,它只是不通過ScriptingException的getter方法發佈它。

太好了。 現在我該怎麼辦?我不知道我將如何使用sun.org.mozilla.javascript.internal.wrappedException,它不是公共類的。

回答

1

Argh。 Java 6的Rhino與sun.org.mozilla.javascript.internal.EvaluatorException做同樣的事情(不通過ScriptingException的方法發佈文件名/行號/ etc),誰知道還有多少其他異常。

我能想到的唯一合理的方式就是使用反射。這是我的解決方案。

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> T getProperty(Object object, String propertyName, 
     Class<T> cl) { 
    try { 
     Object result = getGetterMethod(object, propertyName).invoke(object); 
     return cl.cast(result); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return null; 
}