//
// Copyright (C) 2006 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.vm;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.function.BiFunction;
import cmu.conditional.Conditional;
import cmu.conditional.One;
import de.fosd.typechef.featureexpr.FeatureExpr;
/**
* helper class to store context of an exception
*/
public class ExceptionInfo {
ElementInfo ei;
ThreadInfo ti;
final FeatureExpr ctx;
public ExceptionInfo (FeatureExpr ctx, ThreadInfo xThread, ElementInfo xEi) {
this.ctx = ctx;
ti = xThread;
ei = xEi;
}
public FeatureExpr getCtx() {
return ctx;
}
public ElementInfo getException() {
return ei;
}
public int getExceptionReference () {
return ei.getObjectRef();
}
public String getExceptionClassname() {
return ei.getClassInfo().getName();
}
// Instead of returning only the current Exception name, also return the names of
// its super classes
public HashSet<String> getExceptionClassnames() {
HashSet<String> set = new HashSet<>();
ClassInfo info = ei.getClassInfo();
set.add(info.getName());
while (info.getSuperClass() != null){
info = info.getSuperClass();
set.add(info.getName());
}
return set;
}
public String getDetails() {
StringBuilder sb = new StringBuilder();
sb.append(getExceptionClassname());
int msgRef = ei.getReferenceField("detailMessage").getValue();
if (msgRef != MJIEnv.NULL){
ElementInfo eiMsg = ti.getElementInfo(msgRef);
sb.append(" : ");
sb.append(eiMsg.asString().getValue());
}
String s = sb.toString();
return s;
}
public String getCauseClassname() {
int causeRef = ei.getReferenceField("cause").getValue();
if (causeRef != MJIEnv.NULL){
ElementInfo eiCause = ti.getElementInfo(causeRef);
return eiCause.getClassInfo().getName();
}
return null;
}
public Conditional<String> getCauseDetails(FeatureExpr ctx) {
Conditional<Integer> causeRef = ei.getReferenceField("cause").simplify(ctx).simplify(getCtx());
return causeRef.mapf(ctx, new BiFunction<FeatureExpr, Integer, Conditional<String>>() {
@SuppressWarnings("unchecked")
@Override
public Conditional<String> apply(FeatureExpr ctx, Integer causeRef) {
if (causeRef != MJIEnv.NULL) {
ElementInfo eiCause = ti.getElementInfo(causeRef);
Conditional<Integer> msgRef = eiCause.getReferenceField("detailMessage").simplify(ctx).simplify(getCtx());
return msgRef.mapf(ctx, (FeatureExpr ctx1, Integer msgRef1) -> {
if (msgRef1 != MJIEnv.NULL) {
ElementInfo eiMsg = ti.getElementInfo(msgRef1);
return eiMsg.asString().simplify(ctx1).simplify(getCtx());
}
return (Conditional<String>) One.NULL;
});
}
return (Conditional<String>) One.NULL;
}
});
}
public ThreadInfo getThread() {
return ti;
}
public void printOn (PrintWriter pw){
ti.printStackTrace(ctx, pw, ei.getObjectRef());
}
}