/*
 * This file is covered by the terms of the Common Public License v1.0.
 *
 * Copyright (c) SZEDER Gábor
 *
 * Parts of this software were developed within the JEOPARD research
 * project, which received funding from the European Union's Seventh
 * Framework Programme under grant agreement No. 216682.
 */

package de.fzi.cjunit.jpf.outside;

import gov.nasa.jpf.jvm.DynamicArea;
import gov.nasa.jpf.jvm.ElementInfo;
import gov.nasa.jpf.jvm.JVM;

import de.fzi.cjunit.jpf.exceptioninfo.ExceptionInfo;
import de.fzi.cjunit.jpf.exceptioninfo.StackTraceElementInfo;
import de.fzi.cjunit.jpf.util.ElementInfoWrapper;
import de.fzi.cjunit.jpf.util.StackFrameConverter;


public class ExceptionInfoCollector {

	public ExceptionInfoCollector() { }

	public ExceptionInfo collectFromStack(JVM vm) throws Exception {
		ElementInfo ei = elementInfoFromStack(vm);

		return exceptionInfoFromInfo(ei);
	}

	protected ExceptionInfo exceptionInfoFromInfo(ElementInfo ei) {
		ElementInfoWrapper eiw = new ElementInfoWrapper(ei,
				ExceptionInfo.class);

		StackTraceElementInfo[] stackTrace = stackTraceFromInfo(eiw);

		ExceptionInfo cause = causeFromInfo(eiw);

		return new ExceptionInfo(
				eiw.getStringField("className"),
				eiw.getStringField("message"),
				stackTrace, cause);
	}

	protected ExceptionInfo causeFromInfo(ElementInfoWrapper eiw) {
		ElementInfo cause = eiw.getElementInfoForField("cause");
		if (cause == null) {
			return null;
		} else {
			return exceptionInfoFromInfo(cause);
		}
	}

	protected StackTraceElementInfo[] stackTraceFromInfo(
			ElementInfoWrapper eiw) {
		ElementInfo[] array = eiw.getReferenceArray("stackTrace");
		StackTraceElementInfo[] stackTrace = new StackFrameConverter()
				.toStackTraceElementInfoArray(array);
		return stackTrace;
	}

	protected ElementInfo elementInfoFromStack(JVM vm) throws Exception {
		int argRef = vm.getLastThreadInfo().peek();
		if (argRef == -1) {
			throw new Exception("Cannot examine stack: " +
					"cannot collect ExceptionInfo");
		}

		return elementInfoFromReference(argRef);
	}

	protected ElementInfo elementInfoFromReference(int argRef) {
		return DynamicArea.getHeap().get(argRef);
	}
}

@@ -494,24 +494,93 @@
 eptionInfo;%0A
+import de.fzi.cjunit.jpf.exceptioninfo.MultipleFailureExceptionInfo;%0A
 import de.fz
@@ -625,24 +625,24 @@
 lementInfo;%0A
-
 import de.fz
@@ -917,24 +917,183 @@
 Stack(vm);%0A%0A
+%09%09if (ei.getClassInfo().getName().equals(%0A%09%09%09%09MultipleFailureExceptionInfo.class.getName())) %7B%0A%09%09%09return multipleFailureExceptionInfoFromInfo(ei);%0A%09%09%7D else %7B%0A%09
 %09%09return exc
@@ -1116,16 +1116,20 @@
 fo(ei);%0A
+%09%09%7D%0A
 %09%7D%0A%0A%09pro
@@ -1476,24 +1476,24 @@
 %22message%22),%0A
-
 %09%09%09%09stackTra
@@ -1504,24 +1504,664 @@
 cause);%0A%09%7D%0A%0A
+%09protected MultipleFailureExceptionInfo multipleFailureExceptionInfoFromInfo(%0A%09%09%09ElementInfo ei) %7B%0A%09%09ElementInfoWrapper eiw = new ElementInfoWrapper(ei,%0A%09%09%09%09MultipleFailureExceptionInfo.class);%0A%0A%09%09StackTraceElementInfo%5B%5D stackTrace = stackTraceFromInfo(eiw);%0A%0A%09%09ExceptionInfo cause = causeFromInfo(eiw);%0A%0A%09%09ElementInfo%5B%5D array = eiw.getReferenceArray(%22failures%22);%0A%09%09ExceptionInfo%5B%5D failures = new ExceptionInfo%5Barray.length%5D;%0A%09%09for (int i = 0; i %3C array.length; i++) %7B%0A%09%09%09failures%5Bi%5D = exceptionInfoFromInfo(array%5Bi%5D);%0A%09%09%7D%0A%0A%09%09return new MultipleFailureExceptionInfo(%0A%09%09%09%09eiw.getStringField(%22message%22), stackTrace,%0A%09%09%09%09cause, failures);%0A%09%7D%0A%0A
 %09protected E

support MultipleFailureExceptions