src/main/java/org/perfidix/ouput/AbstractOutput.java
public abstract class AbstractOutput {

	/**
	 * Constant to offer one fix format to display double-variables.
	 */
	protected static final String FLOATFORMAT = "%05.2f";

	/**
	 * Formats a double.
	 *
	 * @param toFormat
	 *            the number to format
	 * @return the formatted string.
	 * @see java.util.Formatter for the documentation.
	 */
	@SuppressWarnings("resource")
	protected static final String format(final double toFormat) {
		return new Formatter(Locale.US).format(FLOATFORMAT, toFormat)
				.toString();
	}

	/**
	 * Visiting the {@link BenchmarkResult} and do something with the result.
	 *
	 * @param res
	 *            the {@link BenchmarkResult}
	 */
	public abstract void visitBenchmark(final BenchmarkResult res);

	/**
	 * Listening to a resultset and handling the data.
	 *
	 * @param meth
	 *            the related {@link Method}
	 * @param meter
	 *            the corresponding {@link AbstractMeter} instance where the
	 *            result is related to
	 * @param data
	 *            the related data
	 * @return if listen is successfil
	 */
	public abstract boolean listenToResultSet(final BenchmarkMethod meth,
			final AbstractMeter meter, final double data);

	/**
	 * Listening to an arised exception.
	 *
	 * @param exec
	 *            an {@link AbstractPerfidixMethodException} instance
	 * @return if listen is successful
	 */
	public abstract boolean listenToException(
			final AbstractPerfidixMethodException exec);

}
src/main/java/org/perfidix/ouput/TabularSummaryOutput.java
public final class TabularSummaryOutput extends AbstractOutput {

    /**
     * Print stream where the result should end.
     */
    private transient final PrintStream out;

    /**
     * Constructor for piping the result to elsewhere.
     *
     * @param paramOut an {@link PrintStream} to pipe to.
     */
    public TabularSummaryOutput(final PrintStream paramOut) {
        super();
        out = paramOut;
    }

    /**
     * Constructor, just giving out on the {@link System#out}.
     */
    public TabularSummaryOutput() {
        this(System.out);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void visitBenchmark(final BenchmarkResult benchRes) {
        final int numberOfColumns = 9;
        NiceTable table = new NiceTable(numberOfColumns);
        table = generateHeader(table);
        for (final AbstractMeter meter : benchRes.getRegisteredMeters()) {
            table.addHeader(meter.getName(), '=', Alignment.Center);
            for (final ClassResult classRes : benchRes.getIncludedResults()) {
                table.addHeader(classRes.getElementName(), '.', Alignment.Left);
                for (final MethodResult methRes : classRes.getIncludedResults()) {
                    table = generateMeterResult(methRes.getElementName(), meter, methRes, table);
                }

                table.addHeader(new StringBuilder("Summary for ").append(classRes.getElementName()).toString(), '_', Alignment.Left);
                table = generateMeterResult("", meter, classRes, table);
                table.addLine('-');

            }
        }
        table.addHeader("Summary for the whole benchmark", '=', Alignment.Center);

        for (final AbstractMeter meter : benchRes.getRegisteredMeters()) {
            table = generateMeterResult("", meter, benchRes, table);
        }

        table.addHeader("Exceptions", '=', Alignment.Center);
        for (final AbstractPerfidixMethodException exec : benchRes.getExceptions()) {
            final StringBuilder execBuilder0 = new StringBuilder();
            execBuilder0.append("Related exception: ").append(exec.getExec().getClass().getSimpleName());
            table.addHeader(execBuilder0.toString(), ' ', Alignment.Left);

            final StringBuilder execBuilder1 = new StringBuilder();
            if (exec instanceof PerfidixMethodInvocationException) {
                execBuilder1.append("Related place: method invocation");
            } else {
                execBuilder1.append("Related place: method check");
            }
            table.addHeader(execBuilder1.toString(), ' ', Alignment.Left);
            if (exec.getMethod() != null) {
                final StringBuilder execBuilder2 = new StringBuilder();
                execBuilder2.append("Related method: ").append(exec.getMethod().getName());
                table.addHeader(execBuilder2.toString(), ' ', Alignment.Left);
            }
            final StringBuilder execBuilder3 = new StringBuilder();
            execBuilder3.append("Related annotation: ").append(exec.getRelatedAnno().getSimpleName());
            table.addHeader(execBuilder3.toString(), ' ', Alignment.Left);
            table.addLine('-');

        }
        table.addLine('=');
        out.println(table.toString());
    }

    /**
     * Generating the results for a given table.
     *
     * @param columnDesc the description for the row
     * @param meter      the corresponding {@link AbstractMeter} instance
     * @param result     the corresponding {@link AbstractResult} instance
     * @param input      the {@link NiceTable} to be print to
     * @return the modified {@link NiceTable} instance
     */
    private NiceTable generateMeterResult(final String columnDesc, final AbstractMeter meter, final AbstractResult result, final NiceTable input) {
        input.addRow(new String[]{columnDesc, meter.getUnit(), AbstractOutput.format(result.sum(meter)), AbstractOutput.format(result.min(meter)), AbstractOutput.format(result.max(meter)), AbstractOutput.format(result.mean(meter)), AbstractOutput.format(result.getStandardDeviation(meter)), new StringBuilder("[").append(AbstractOutput.format(result.getConf05(meter))).append("-").append(AbstractOutput.format(result.getConf95(meter))).append("]").toString(), AbstractOutput.format(result.getResultSet(meter).size())});
        return input;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean listenToResultSet(final BenchmarkMethod meth, final AbstractMeter meter, final double data) {
        Method m = meth.getMethodToBench();
        final StringBuilder builder = new StringBuilder();
        builder.append("Class: ").append(m.getDeclaringClass().getSimpleName()).append("#").append(m.getName());
        builder.append("\nMeter: ").append(meter.getName());
        builder.append("\nData: ").append(data).append("\n");
        out.println(builder.toString());
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean listenToException(final AbstractPerfidixMethodException exec) {
        final StringBuilder builder = new StringBuilder();
        if (exec.getMethod() != null) {
            builder.append("Class: ").append(exec.getMethod().getDeclaringClass().getSimpleName()).append("#").append(exec.getMethod().getName()).append("\n");
        }
        builder.append("Annotation: ").append(exec.getRelatedAnno().getSimpleName());
        builder.append("\nException: ").append(exec.getClass().getSimpleName()).append("/").append(exec.getExec().toString());
        out.println(builder.toString());
        exec.getExec().printStackTrace(out);
        return true;

    }

    /**
     * Generating header for a given table.
     *
     * @param table the table where the header should fit to
     * @return another {@link NiceTable} instance
     */
    private NiceTable generateHeader(final NiceTable table) {
        table.addHeader("Benchmark");
        table.addRow(new String[]{"-", "unit", "sum", "min", "max", "avg", "stddev", "conf95", "runs"});
        return table;
    }

}
src/main/java/org/perfidix/exceptions/SocketViewException.java
public final class SocketViewException extends IOException {

    /**
     * Serial ID
     */
    private static final long serialVersionUID = 528281733888231478L;

    private transient final IOException exc;

    /**
     * Constructor
     *
     * @param paramToStore exception to encapsulate
     */
    public SocketViewException(final IOException paramToStore) {
        super();
        exc = paramToStore;
    }

    /**
     * Returns the occurred exception.
     *
     * @return The exception occurred.
     */
    public IOException getExc() {
        return exc;
    }

}
src/main/java/org/perfidix/Perfidix.java
public final class Perfidix {

    /**
     * private constructor.
     */
    private Perfidix() {
    }

    /**
     * Running one Benchmark.
     *
     * @param benchs to be inserted
     * @return one {@link BenchmarkResult} object with the results
     * @throws ClassNotFoundException if class cannot be found
     * @throws IllegalAccessException if conf cannot be instantiated
     * @throws InstantiationException if conf cannot be instantiated
     */
    public static BenchmarkResult runBenchs(final String[] benchs) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        final AbstractConfig conf = getConfiguration(benchs);

        final Benchmark bench = new Benchmark(conf);
        return setUpBenchmark(benchs, bench).run();
    }

    /**
     * Setting up an existing benchmark with the given number of class-files
     *
     * @param classes   to be benched
     * @param benchmark to be set up
     * @return the same {@link Benchmark} object with the classes
     * @throws ClassNotFoundException thrown if class was not found.
     */
    public static Benchmark setUpBenchmark(final String[] classes, final Benchmark benchmark) throws ClassNotFoundException {
        for (final String each : classes) {
            benchmark.add(Class.forName(each));
        }
        return benchmark;
    }

    /**
     * Getting a configuration out of the class-files. If none is avaliable, the {@link StandardConfig} is given back.
     * The {@link AbstractConfig} instance has to have a parameter-free constructor.
     *
     * @param classes to be examined. Only one instance of an {@link AbstractConfig} is allowed.
     * @return the {@link AbstractConfig} instance or the {@link StandardConfig} if none was found.
     * @throws ClassNotFoundException thrown if a class was not found.
     * @throws InstantiationException thrown if the {@link AbstractConfig} instance was not able to be instaniated
     * @throws IllegalAccessException thrown if the {@link AbstractConfig} instance was not able to be instaniated
     */
    public static AbstractConfig getConfiguration(final String[] classes) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        AbstractConfig conf = null;
        for (String each : classes) {
            final Class<?> clazz = Class.forName(each);
            final Class<?> superclazz = clazz.getSuperclass();
            if (superclazz.equals(AbstractConfig.class)) {
                if (conf == null) {
                    conf = (AbstractConfig) clazz.newInstance();
                } else {
                    throw new IllegalArgumentException("Only one config-class allowed");
                }
            }
        }
        if (conf == null) {
            conf = new StandardConfig();
        }
        return conf;
    }

    /**
     * Main method for invoking benchs with classes as strings.
     *
     * @param args the classes
     * @throws ClassNotFoundException if class cannot be found
     * @throws IllegalAccessException if conf cannot be instantiated
     * @throws InstantiationException if conf cannot be instantiated
     */
    public static void main(final String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        final BenchmarkResult res = runBenchs(args);
        new TabularSummaryOutput().visitBenchmark(res);
    }
}
src/main/java/org/perfidix/element/BenchmarkMethod.java
public final class BenchmarkMethod {

	/**
	 * Method to be benched.
	 */
	private transient final Method methodToBench;

	/**
	 * Getting dataprovider method.
	 */
	private transient Method dataProvider;

	/**
	 * Constructor, with a definite method to bench. The method has to be
	 * checked with {@link BenchmarkMethod#isBenchmarkable(Method)} first,
	 * otherwise an IllegalArgumentException could arise.
	 *
	 * @param paramMethod
	 *            method to be benched (eventually)
	 * @throws PerfidixMethodCheckException
	 *             if method is not benchmarkable
	 */
	public BenchmarkMethod(final Method paramMethod)
			throws PerfidixMethodCheckException {
		methodToBench = paramMethod;
		setDataProvider(findDataProvider());
	}

	/**
	 * Getting the number of runs corresponding to a given method. The method
	 * MUST be a benchmarkable method, otherwise an IllegalStateException
	 * exception arises. The number of runs of an annotated method is more
	 * powerful than the number of runs as denoted by the benchclass annotation.
	 *
	 * @param meth
	 *            to be checked
	 * @return the number of runs of this benchmarkable-method
	 */
	public static int getNumberOfAnnotatedRuns(final Method meth) {
		if (!isBenchmarkable(meth)) {
			throw new IllegalArgumentException("Method " + meth
					+ " must be a benchmarkable method.");
		}
		final Bench benchAnno = meth.getAnnotation(Bench.class);
		final BenchClass benchClassAnno = meth.getDeclaringClass()
				.getAnnotation(BenchClass.class);
		int returnVal;
		if (benchAnno == null) {
			returnVal = benchClassAnno.runs();
		} else {
			returnVal = benchAnno.runs();
			// use runs from @BenchClass if none is set on method (issue #4)
			if ((returnVal == Bench.NONE_RUN) && (benchClassAnno != null)) {
				returnVal = benchClassAnno.runs();
			}
		}
		return returnVal;
	}

	/**
	 * This class finds any method with a given annotation. The method is
	 * allowed to occur only once in the class and should match the requirements
	 * for Perfidix for an execution by reflection.
	 *
	 * @param anno
	 *            of the method to be found
	 * @param clazz
	 *            class to be searched
	 * @return a method annotated by the annotation given. The method occurs
	 *         only once in the class and matched the requirements of
	 *         perfidix-reflective-invocation.
	 * @throws PerfidixMethodCheckException
	 *             if these integrity checks fail
	 */
	public static Method findAndCheckAnyMethodByAnnotation(
			final Class<?> clazz, final Class<? extends Annotation> anno)
			throws PerfidixMethodCheckException {
		// needed variables, one for check for duplicates
		Method anyMethod = null;

		// Scanning all methods
		final Method[] possAnnoMethods = clazz.getDeclaredMethods();
		for (final Method meth : possAnnoMethods) {
			if (meth.getAnnotation(anno) != null) {
				// Check if there are multiple annotated methods, throwing
				// IllegalAccessException otherwise.
				if (anyMethod == null) {
					// Check if method is valid (no param, no returnval,
					// etc.), throwing IllegalAccessException otherwise.
					if (isReflectedExecutable(meth, anno)) {
						anyMethod = meth;
					} else {
						throw new PerfidixMethodCheckException(
								new IllegalAccessException(anno.toString()
										+ "-annotated method " + meth
										+ " is not executable."), meth, anno);
					}
				} else {
					throw new PerfidixMethodCheckException(
							new IllegalAccessException("Please use only one "
									+ anno.toString()
									+ "-annotation in one class."), meth, anno);
				}
			}
		}

		return anyMethod;
	}

	/**
	 * This method should act as a check to guarantee that only specific
	 * Benchmarkables are used for benching.
	 *
	 * @param meth
	 *            method to be checked.
	 * @return true if an instance of this interface is benchmarkable, false
	 *         otherwise.
	 */
	public static boolean isBenchmarkable(final Method meth) {
		boolean returnVal = true;

		// Check if bench-anno is given. For testing purposes against
		// before/after annos
		final Bench benchAnno = meth.getAnnotation(Bench.class);

		// if method is annotated with SkipBench, the method is never
		// benchmarkable.
		final SkipBench skipBenchAnno = meth.getAnnotation(SkipBench.class);
		if (skipBenchAnno != null) {
			returnVal = false;
		}

		// Check if method is defined as beforeClass, beforeFirstRun,
		// beforeEachRun, afterEachRun, afterLastRun, afterClass. A method can
		// either be a before/after class or afterwards be benchmarkable through
		// the BenchClass annotation.
		final BeforeBenchClass beforeClass = meth
				.getAnnotation(BeforeBenchClass.class);
		if (beforeClass != null && benchAnno == null) {
			returnVal = false;
		}

		final BeforeFirstRun beforeFirstRun = meth
				.getAnnotation(BeforeFirstRun.class);
		if (beforeFirstRun != null && benchAnno == null) {
			returnVal = false;
		}

		final BeforeEachRun beforeEachRun = meth
				.getAnnotation(BeforeEachRun.class);
		if (beforeEachRun != null && benchAnno == null) {
			returnVal = false;
		}

		final AfterEachRun afterEachRun = meth
				.getAnnotation(AfterEachRun.class);
		if (afterEachRun != null && benchAnno == null) {
			returnVal = false;
		}

		final AfterLastRun afterLastRun = meth
				.getAnnotation(AfterLastRun.class);
		if (afterLastRun != null && benchAnno == null) {
			returnVal = false;
		}

		final AfterBenchClass afterClass = meth
				.getAnnotation(AfterBenchClass.class);
		if (afterClass != null && benchAnno == null) {
			returnVal = false;
		}

		// if method is not annotated with Bench and class is not annotated with
		// BenchClass, the method is never benchmarkable.
		final BenchClass classBenchAnno = meth.getDeclaringClass()
				.getAnnotation(BenchClass.class);
		if (benchAnno == null && classBenchAnno == null) {
			returnVal = false;
		}

		// check if method is executable for perfidix purposes.
		if (!isReflectedExecutable(meth, Bench.class)) {
			returnVal = false;
		}
		return returnVal;
	}

	/**
	 * Checks if this method is executable via reflection for perfidix purposes.
	 * That means that the method has no parameters (except for , no
	 * return-value, is non-static, is public and throws no exceptions.
	 *
	 * @param meth
	 *            method to be checked
	 * @param anno
	 *            anno for method to be check, necessary since different
	 *            attributes are possible depending on the anno
	 * @return true if method matches requirements.
	 */
	public static boolean isReflectedExecutable(final Method meth,
			final Class<? extends Annotation> anno) {
		boolean returnVal = true;
		// Check if DataProvider is valid if set.
		if (anno.equals(DataProvider.class)
				&& !meth.getReturnType().isAssignableFrom(Object[][].class)) {
			returnVal = false;
		}
		// for all other methods, the return type must be void
		if (!anno.equals(DataProvider.class)
				&& !meth.getGenericReturnType().equals(Void.TYPE)) {
			returnVal = false;
		}

		// if method is static, the method is not benchmarkable
		if (!(anno.equals(BeforeBenchClass.class))
				&& Modifier.isStatic(meth.getModifiers())) {
			returnVal = false;
		}
		// if method is not public, the method is not benchmarkable
		if (!Modifier.isPublic(meth.getModifiers())) {
			returnVal = false;
		}

		return returnVal;
	}

	/**
	 * Method to find a {@link BeforeFirstRun} annotation. This method should be
	 * invoked for all methods. The corresponding class is searched after
	 * suitable methods and checks for integrity are made. If there are multiple
	 * {@link BeforeFirstRun} -annotated methods available, an exception is
	 * thrown. If there are designated special {@link BeforeFirstRun} methods as
	 * given in the parameter of the {@link Bench}-annotation, this method is
	 * taken with any further checking of the other methods in the class.
	 *
	 * @return Annotated method with BeforeFirstRun annotation, null of none
	 *         exists
	 * @throws PerfidixMethodCheckException
	 *             if integrity check of class and method fails.
	 * @see BeforeFirstRun
	 * @see Bench
	 */
	public Method[] findBeforeFirstRun() throws PerfidixMethodCheckException {

		Method method = null;

		final Bench benchAnno = getMethodToBench().getAnnotation(Bench.class);
		if (benchAnno != null && !benchAnno.beforeFirstRun().equals("")) {
			List<Method> returnval = new ArrayList<Method>();

			try {
				// variable to instantiate the method by name.
				final Class<?>[] setUpParams = {};

				String[] methods = benchAnno.beforeFirstRun().split(",");
				for (String methodString : methods) {
					// getting the method by name
					method = getMethodToBench()
							.getDeclaringClass()
							.getDeclaredMethod(methodString.trim(), setUpParams);

					if (isReflectedExecutable(method, BeforeFirstRun.class)) {
						returnval.add(method);
					} else {
						throw new PerfidixMethodCheckException(
								new IllegalAccessException(
										"Failed to execute BeforeFirstRun-annotated method "
												+ method), method,
								BeforeFirstRun.class);
					}
				}
				return returnval.toArray(new Method[returnval.size()]);

			} catch (final SecurityException e) {
				throw new PerfidixMethodCheckException(e, method,
						BeforeFirstRun.class);
			} catch (final NoSuchMethodException e) {
				throw new PerfidixMethodCheckException(e, method,
						BeforeFirstRun.class);
			}
		}

		// if there was no name, a scan over the class occurs, otherwise the
		// designated method is checked.
		else {
			Method meth = findAndCheckAnyMethodByAnnotation(getMethodToBench()
					.getDeclaringClass(), BeforeFirstRun.class);
			if (meth == null) {
				return new Method[0];
			} else {
				return new Method[] { meth };
			}
		}

	}

	/**
	 * Method to find a {@link BeforeEachRun} annotation. This method should be
	 * invoked for all methods. The corresponding class is searched after
	 * suitable methods and checks for integrity are made. If there are multiple
	 * {@link BeforeEachRun} -annotated methods available, an exception is
	 * thrown. If there are designated special {@link BeforeEachRun} methods as
	 * given in the parameter of the {@link Bench}-annotation, this method is
	 * taken with any further checking of the other methods in the class.
	 *
	 * @return Annotated method with BeforeEachRun annotation, null of none
	 *         exists
	 * @throws PerfidixMethodCheckException
	 *             if integrity check of class and method fails.
	 * @see BeforeEachRun
	 * @see Bench
	 */
	public Method[] findBeforeEachRun() throws PerfidixMethodCheckException {

		Method method = null;

		final Bench benchAnno = getMethodToBench().getAnnotation(Bench.class);
		if (benchAnno != null && !benchAnno.beforeEachRun().equals("")) {
			final List<Method> returnval = new ArrayList<>();
			try {

				String[] methods = benchAnno.beforeEachRun().split(",");
				for (String methodString : methods) {

					// getting the method by name
					method = getMethodToBench().getDeclaringClass()
							.getDeclaredMethod(methodString.trim());
					if (isReflectedExecutable(method, BeforeEachRun.class)) {
						returnval.add(method);
					} else {
						throw new PerfidixMethodCheckException(
								new IllegalAccessException(
										"Failed to execute BeforeEachRun-annotated method "
												+ method), method,
								BeforeEachRun.class);
					}
				}
				return returnval.toArray(new Method[returnval.size()]);

			} catch (SecurityException e) {
				throw new PerfidixMethodCheckException(e, method,
						BeforeEachRun.class);
			} catch (NoSuchMethodException e) {
				throw new PerfidixMethodCheckException(e, method,
						BeforeEachRun.class);
			}
		} else {

			// if there was no name, a scan over the class occurs, otherwise the
			// designated method is checked.
			Method meth = findAndCheckAnyMethodByAnnotation(getMethodToBench()
					.getDeclaringClass(), BeforeEachRun.class);
			if (meth == null) {
				return new Method[0];
			} else {
				return new Method[] { meth };
			}

		}
	}

	/**
	 * Method to find a {@link AfterEachRun} annotation. This method should be
	 * invoked for all methods. The corresponding class is searched after
	 * suitable methods and checks for integrity are made. If there are multiple
	 * {@link AfterEachRun} -annotated methods available, an exception is
	 * thrown. If there are designated special {@link AfterEachRun} methods as
	 * given in the parameter of the {@link Bench}-annotation, this method is
	 * taken with any further checking of the other methods in the class.
	 *
	 * @return Annotated method with AfterEachRun annotation, null of none
	 *         exists
	 * @throws PerfidixMethodCheckException
	 *             if integrity check of class and method fails.
	 * @see AfterEachRun
	 * @see Bench
	 */
	public Method[] findAfterEachRun() throws PerfidixMethodCheckException {

		Method method = null;

		final Bench benchAnno = getMethodToBench().getAnnotation(Bench.class);
		if (benchAnno != null && !benchAnno.afterEachRun().equals("")) {
			List<Method> returnval = new ArrayList<Method>();
			try {

				String[] methods = benchAnno.afterEachRun().split(",");
				for (String methodString : methods) {

					// getting the method by name
					method = getMethodToBench().getDeclaringClass()
							.getDeclaredMethod(methodString.trim());
					if (isReflectedExecutable(method, AfterEachRun.class)) {
						returnval.add(method);
					} else {
						throw new PerfidixMethodCheckException(
								new IllegalAccessException(
										"AfterEachRun-annotated method "
												+ method
												+ " is not executable."),
								method, AfterEachRun.class);
					}
				}
				return returnval.toArray(new Method[returnval.size()]);
			} catch (SecurityException e) {
				throw new PerfidixMethodCheckException(e, method,
						AfterEachRun.class);
			} catch (NoSuchMethodException e) {
				throw new PerfidixMethodCheckException(e, method,
						AfterEachRun.class);
			}
		} else {
			// if there was no name, a scan over the class occurs, otherwise the
			// designated method is checked.
			Method meth = findAndCheckAnyMethodByAnnotation(getMethodToBench()
					.getDeclaringClass(), AfterEachRun.class);
			if (meth == null) {
				return new Method[0];
			} else {
				return new Method[] { meth };
			}

		}
	}

	/**
	 * Method to find a {@link AfterLastRun} annotation. This method should be
	 * invoked for all methods. The corresponding class is searched after
	 * suitable methods and checks for integrity are made. If there are multiple
	 * {@link AfterLastRun} -annotated methods available, an exception is
	 * thrown. If there are designated special {@link AfterLastRun} methods as
	 * given in the parameter of the {@link Bench}-annotation, this method is
	 * taken with any further checking of the other methods in the class.
	 *
	 * @return Annotated method with AfterLastRun annotation, null of none
	 *         exists
	 * @throws PerfidixMethodCheckException
	 *             if integrity check of class and method fails.
	 * @see AfterLastRun
	 * @see Bench
	 */
	public Method[] findAfterLastRun() throws PerfidixMethodCheckException {

		Method method = null;

		final Bench benchAnno = getMethodToBench().getAnnotation(Bench.class);
		if (benchAnno != null && !benchAnno.afterLastRun().equals("")) {
			List<Method> returnval = new ArrayList<Method>();
			try {
				// variable to instantiate the method by name.
				final Class<?>[] setUpParams = {};

				String[] methods = benchAnno.afterLastRun().split(",");
				for (String methodString : methods) {
					// getting the method by name
					method = getMethodToBench()
							.getDeclaringClass()
							.getDeclaredMethod(methodString.trim(), setUpParams);

					if (isReflectedExecutable(method, AfterLastRun.class)) {
						returnval.add(method);
					} else {
						throw new PerfidixMethodCheckException(
								new IllegalAccessException(
										"AfterLastRun-annotated method "
												+ method
												+ " is not executable."),
								method, AfterLastRun.class);
					}
				}
				return returnval.toArray(new Method[returnval.size()]);
			} catch (final SecurityException e) {
				throw new PerfidixMethodCheckException(e, method,
						AfterLastRun.class);
			} catch (final NoSuchMethodException e) {
				throw new PerfidixMethodCheckException(e, method,
						AfterLastRun.class);
			}
		} else {
			// if there was no name, a scan over the class occurs, otherwise the
			// designated method is checked.
			Method meth = findAndCheckAnyMethodByAnnotation(getMethodToBench()
					.getDeclaringClass(), AfterLastRun.class);
			if (meth == null) {
				return new Method[0];
			} else {
				return new Method[] { meth };
			}
		}
	}

	/**
	 * This method checks whether a method uses a data provider for dynamic
	 * input
	 *
	 * @return true if method is parameterized, false otherwise
	 * @throws PerfidixMethodCheckException
	 */
	private Method findDataProvider() throws PerfidixMethodCheckException {

		final Bench benchAnno = getMethodToBench().getAnnotation(Bench.class);
		Method dataProvider = null;
		if (benchAnno != null && !benchAnno.dataProvider().equals("")) {
			try {
				// Getting the String name for the dataProvider
				final String dataProviderIdentifier = benchAnno.dataProvider();
				// Check if there is a Dataprovider with the name as identifier
				for (final Method eachMeth : getMethodToBench()
						.getDeclaringClass().getMethods()) {
					DataProvider anno = eachMeth
							.getAnnotation(DataProvider.class);
					if (anno != null
							&& anno.name().equals(dataProviderIdentifier)) {
						if (dataProvider == null) {
							dataProvider = eachMeth;
						} else {
							throw new PerfidixMethodCheckException(
									new RuntimeException(
											"Only one Dataprovider allowed, but found "
													+ dataProvider + " and "
													+ eachMeth), eachMeth,
									DataProvider.class);
						}
					}
				}
				// if not, try to find a method with the name
				if (dataProvider == null) {
					dataProvider = getMethodToBench().getDeclaringClass()
							.getDeclaredMethod(dataProviderIdentifier);
				}

				// perform the checks same as testng: two dimensional array for
				// return val, parameter is mapping of
				// class, array of instances.
				// checking return types of dataprovider method
				final Class<?> returnType = dataProvider.getReturnType();
				// final Class<?>[] parameters = meth.getParameterTypes();
				if (Object[][].class.isAssignableFrom(returnType)) {
					// checking input types of bench method against the return
					// types of the parameter
					// Class<Object[][]> castedReturnType = (Class<Object[][]>)
					// returnType;
					// TODO implement check
				}
			} catch (NoSuchMethodException | SecurityException e) {
				// no data provider method, will be returned as false anyhow
			}
		}
		return dataProvider;
	}

	/**
	 * Simple getter for encapsulated method.
	 *
	 * @return the methodToBench
	 */
	public Method getMethodToBench() {
		return methodToBench;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		if (methodToBench == null) {
			result = prime * result;
		} else {
			result = prime * result + methodToBench.hashCode();
		}

		return result;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean equals(final Object obj) {
		return obj.hashCode() == this.hashCode();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String toString() {
		return methodToBench.getName();
	}

	/**
	 * This method returns the fully qualified name consisting of its own name
	 * and its class name
	 *
	 * @return the {@link String} name von the bench method consisting of fully
	 *         qualified name of its class and its own name
	 */
	public String getMethodWithClassName() {
		return methodToBench.getDeclaringClass().getName() + "."
				+ methodToBench.getName();
	}

	public Method getDataProvider() {
		return dataProvider;
	}

	void setDataProvider(Method dataProvider) {
		this.dataProvider = dataProvider;
	}

}
src/main/java/org/perfidix/Benchmark.java
public final class Benchmark {

	/**
	 * Simple random for gc-prob
	 */
	private transient static final Random RAN = new Random();
	/**
	 * Set with all used classes.
	 */
	private transient final Set<Class<?>> clazzes;
	/**
	 * Already instantiated objects
	 */
	private transient final Set<Object> objects;
	/**
	 * Configuration of benchmark, holding everything.
	 */
	private transient final AbstractConfig conf;

	/**
	 * Constructor with a fixed set of used meters.
	 *
	 * @param paramConf
	 *            Configuration for Benchmark
	 */
	public Benchmark(final AbstractConfig paramConf) {
		conf = paramConf;
		this.clazzes = new LinkedHashSet<Class<?>>();
		this.objects = new LinkedHashSet<Object>();

	}

	/**
	 * Convenience constructor using the {@link StandardConfig}
	 */
	public Benchmark() {
		this(new StandardConfig());
	}

	/**
	 * Getting the content of a dataprovider.
	 *
	 * @param meth
	 *            the dataprovider method
	 * @param toInvoke
	 *            the object on which the method is invoked
	 * @return a two-dimensional array containing multiple sets of parameters
	 *         representing single runs each.
	 */
	private static Object[][] getDataProviderContent(final Method meth,
			final Object toInvoke) {

		Object[][] res;
		try {
			res = (Object[][]) meth.invoke(toInvoke);
		} catch (IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			throw new IllegalArgumentException("Method " + meth
					+ " as data provider throws an exception on invocation");
		}

		return res;
	}

	/**
	 * Adding a class to bench to this benchmark. This class should contain
	 * benchmarkable methods, otherwise it will be ignored.
	 *
	 * @param clazz
	 *            to be added.
	 */
	public void add(final Class<?> clazz) {
		if (this.clazzes.contains(clazz)) {
			throw new IllegalArgumentException(
					"Only one class-instance per benchmark allowed");
		} else {
			this.clazzes.add(clazz);
		}
	}

	/**
	 * Adding a already instantiated objects to benchmark. Per benchmark, only
	 * one objects of each class is allowed.
	 *
	 * @param obj
	 *            to be added
	 */
	public void add(final Object obj) {
		final Class<?> clazz = obj.getClass();

		if (this.clazzes.contains(clazz)) {
			throw new IllegalArgumentException(
					"Only one class-instance per benchmark allowed");
		} else {
			this.clazzes.add(clazz);
			this.objects.add(obj);
		}
	}

	/**
	 * Getting the number of all methods and all runs
	 *
	 * @return a map with all methods and the runs.
	 * @throws PerfidixMethodCheckException
	 *             if methods are not bechmarkable
	 */
	public Map<BenchmarkMethod, Integer> getNumberOfMethodsAndRuns()
			throws PerfidixMethodCheckException {
		final Map<BenchmarkMethod, Integer> returnVal = new HashMap<BenchmarkMethod, Integer>();
		// instantiate objects, just for getting runs
		final List<BenchmarkMethod> meths = getBenchmarkMethods();
		for (final BenchmarkMethod meth : meths) {
			// TODO respect data provider
			int numberOfRuns = BenchmarkMethod.getNumberOfAnnotatedRuns(meth
					.getMethodToBench());
			if (numberOfRuns == Bench.NONE_RUN) {
				numberOfRuns = conf.getRuns();
			}
			returnVal.put(meth, numberOfRuns);
		}
		return returnVal;
	}

	/**
	 * Running this benchmark
	 *
	 * @return {@link BenchmarkResult} the result in an {@link BenchmarkResult}
	 *         container.
	 */
	public BenchmarkResult run() {
		final BenchmarkResult res = new BenchmarkResult(conf.getListener());
		BenchmarkExecutor.initialize(conf, res);

		// instantiate methods
		final Map<Class<?>, Object> instantiatedObjs = instantiateObjects(res);

		// getting Benchmarkables
		try {
			final List<BenchmarkElement> elements = getBenchmarkElements(instantiatedObjs);

			// arranging them
			final AbstractMethodArrangement arrangement = AbstractMethodArrangement
					.getMethodArrangement(elements, conf.getArrangement());

			// getting the mapping and executing beforemethod
			final Map<Class<?>, Object> objectsToExecute = executeBeforeBenchClass(
					instantiatedObjs, res);

			// executing the bench for the arrangement
			for (final BenchmarkElement elem : arrangement) {
				// invoking gc if possible
				if (RAN.nextDouble() < conf.getGcProb()) {
					System.gc();
				}

				final BenchmarkExecutor exec = BenchmarkExecutor
						.getExecutor(elem);

				final Object obj = objectsToExecute.get(elem.getMeth()
						.getMethodToBench().getDeclaringClass());
				// check needed because of failed initialization of objects
				if (obj != null) {
					exec.executeBeforeMethods(obj);
					exec.executeBench(obj, elem.getParameter());
					exec.executeAfterMethods(obj);
				}
			}

			// cleaning up methods to benchmark
			tearDownObjectsToExecute(objectsToExecute, res);
		} catch (PerfidixMethodCheckException exc) {
			res.addException(exc);
		}
		return res;
	}

	/**
	 * Setting up executable objects for all registered classes and executing
	 * {@link BeforeBenchClass} annotated methods. If an {@link Exception}
	 * occurs, this failure will be stored in the {@link BenchmarkResult} and
	 * the class will not be instantiated
	 *
	 * @param res
	 *            {@link BenchmarkResult} for storing possible failures.
	 * @return a mapping with class->objects for all registered classes-
	 */
	private Map<Class<?>, Object> instantiateObjects(final BenchmarkResult res) {
		// datastructure initialization for all objects
		final Map<Class<?>, Object> objectsToUse = new Hashtable<Class<?>, Object>();

		// generating including already instaniated objects
		for (final Object obj : this.objects) {
			final Class<?> clazz = obj.getClass();
			objectsToUse.put(clazz, obj);
		}

		// generating objects for each registered class
		for (final Class<?> clazz : clazzes) {
			// generating a new instance on which the benchmark will be
			// performed if there isn't a user generated one
			if (!objectsToUse.containsKey(clazz)) {
				try {
					final Object obj = clazz.newInstance();
					objectsToUse.put(clazz, obj);
					// otherwise adding an exception to the result
				} catch (final InstantiationException | IllegalAccessException e) {
					res.addException(new PerfidixMethodInvocationException(e,
							BeforeBenchClass.class));
				}
			}
		}

		return objectsToUse;
	}

	/**
	 * Executing beforeBenchClass if present.
	 *
	 * @param instantiatedObj
	 *            with the instantiatedObj;
	 * @param res
	 *            where the Exceptions should be stored to
	 * @return valid instances with valid beforeCall
	 */
	private Map<Class<?>, Object> executeBeforeBenchClass(
			final Map<Class<?>, Object> instantiatedObj,
			final BenchmarkResult res) {

		final Map<Class<?>, Object> returnVal = new Hashtable<Class<?>, Object>();

		// invoking before bench class
		for (final Class<?> clazz : instantiatedObj.keySet()) {

			final Object objectToUse = instantiatedObj.get(clazz);
			// ..the search for the beforeClassMeth begins...
			Method beforeClassMeth = null;
			boolean continueVal = true;
			try {
				beforeClassMeth = BenchmarkMethod
						.findAndCheckAnyMethodByAnnotation(clazz,
								BeforeBenchClass.class);
				// ... and if this search is throwing an exception, the
				// exception will be added and a flag is set to break up
			} catch (final PerfidixMethodCheckException e) {
				res.addException(e);
				continueVal = false;
			}
			// if everything worked well...
			if (continueVal) {
				if (beforeClassMeth == null) {
					// ...either the objects is directly mapped to the class
					// for executing the benches
					returnVal.put(clazz, objectToUse);
				} else {
					// ... or the beforeMethod will be executed and a
					// possible exception stored to the result...
					final PerfidixMethodCheckException beforeByCheck = BenchmarkExecutor
							.checkMethod(objectToUse, BeforeBenchClass.class,
									beforeClassMeth);
					if (beforeByCheck == null) {
						final PerfidixMethodInvocationException beforeByInvok = BenchmarkExecutor
								.invokeMethod(objectToUse,
										BeforeBenchClass.class, beforeClassMeth);
						if (beforeByInvok == null) {
							returnVal.put(clazz, objectToUse);
						} else {
							res.addException(beforeByInvok);
						}
					} else {
						res.addException(beforeByCheck);
					}
				}
			}
		}
		return returnVal;
	}

	/**
	 * Tear down executable objects for all registered classes and executing
	 * {@link AfterBenchClass} annotated methods.
	 *
	 * @param objects
	 *            a mapping with class->objects to be teared down
	 * @param res
	 *            the {@link BenchmarkResult} for storing possible failures.
	 */
	private void tearDownObjectsToExecute(final Map<Class<?>, Object> objects,
			final BenchmarkResult res) {

		// executing tearDown for all clazzes registered in given Map
		for (final Class<?> clazz : objects.keySet()) {
			final Object objectToUse = objects.get(clazz);
			if (objectToUse != null) {
				// executing AfterClass for all objects.
				Method afterClassMeth = null;
				try {
					afterClassMeth = BenchmarkMethod
							.findAndCheckAnyMethodByAnnotation(clazz,
									AfterBenchClass.class);
				} catch (final PerfidixMethodCheckException e) {
					res.addException(e);
				}
				// if afterClassMethod exists, the method will be executed and
				// possible failures will be stored in the BenchmarkResult
				if (afterClassMeth != null) {
					final PerfidixMethodCheckException afterByCheck = BenchmarkExecutor
							.checkMethod(objectToUse, AfterBenchClass.class,
									afterClassMeth);
					if (afterByCheck == null) {
						final PerfidixMethodInvocationException afterByInvok = BenchmarkExecutor
								.invokeMethod(objectToUse,
										AfterBenchClass.class, afterClassMeth);
						if (afterByInvok != null) {
							res.addException(afterByInvok);
						}
					} else {
						res.addException(afterByCheck);
					}
				}
			}
		}
	}

	/**
	 * Getting all Benchmarkable methods out of the registered class.
	 *
	 * @return a Set with {@link BenchmarkMethod}
	 * @throws PerfidixMethodCheckException
	 */
	List<BenchmarkMethod> getBenchmarkMethods()
			throws PerfidixMethodCheckException {
		// Generating Set for returnVal
		final List<BenchmarkMethod> elems = new ArrayList<BenchmarkMethod>();
		// Getting all Methods and testing if its benchmarkable
		for (final Class<?> clazz : clazzes) {
			for (final Method meth : clazz.getDeclaredMethods()) {
				// Check if benchmarkable, if so, insert to returnVal;
				if (BenchmarkMethod.isBenchmarkable(meth)) {
					final BenchmarkMethod benchmarkMeth = new BenchmarkMethod(
							meth);
					elems.add(benchmarkMeth);
				}
			}
		}
		return elems;
	}

	/**
	 * Getting all benchmarkable objects out of the registered classes with the
	 * annotated number of runs.
	 *
	 * @param paramObjs
	 *            a set with all existing objects for getting data from the
	 *            dataproviders
	 * @return a Set with {@link BenchmarkMethod}
	 * @throws PerfidixMethodCheckException
	 */
	private List<BenchmarkElement> getBenchmarkElements(
			final Map<Class<?>, Object> paramObjs)
			throws PerfidixMethodCheckException {

		final List<BenchmarkElement> elems = new ArrayList<BenchmarkElement>();
		final List<BenchmarkMethod> meths = getBenchmarkMethods();

		for (final BenchmarkMethod meth : meths) {

			final Method dataProv = meth.getDataProvider();
			// Test if benchmark is parameterized. If not..
			if (dataProv == null) {
				// ...simple execute the benchrun on the base of the runs set...
				int numberOfRuns = BenchmarkMethod
						.getNumberOfAnnotatedRuns(meth.getMethodToBench());
				if (numberOfRuns == Bench.NONE_RUN) {
					numberOfRuns = conf.getRuns();
				}

				// ...and adding this number of
				// elements to the set to be evaluated.
				for (int i = 0; i < numberOfRuns; i++) {
					elems.add(new BenchmarkElement(meth));
				}
			}// If the method is parameterized...
			else {
				// ..get the parameters
				final Object[][] dataProvider = getDataProviderContent(
						dataProv, paramObjs.get(meth.getMethodToBench()
								.getDeclaringClass()));
				for (final Object[] parameterSet : dataProvider) {
					elems.add(new BenchmarkElement(meth, parameterSet));
				}

				// TODO continue over here
			}
		}

		return elems;
	}
}
src/main/java/org/perfidix/exceptions/PerfidixMethodCheckException.java
public final class PerfidixMethodCheckException extends AbstractPerfidixMethodException {

    /**
     * serializable id.
     */
    private static final long serialVersionUID = -2181496089750788312L;

    /**
     * Constructor.
     *
     * @param paramExec       encapsulated exception
     * @param paramMeth       the method where the error occured
     * @param paramAnnotation the related annotation of the method
     */
    public PerfidixMethodCheckException(final Throwable paramExec, final Method paramMeth, final Class<? extends Annotation> paramAnnotation) {
        super(paramExec, paramMeth, paramAnnotation);
    }

}
src/main/java/org/perfidix/meter/AbstractMeter.java
public abstract class AbstractMeter {

    /**
     * Getting the current value for this meter.
     *
     * @return the current tick value.
     */
    public abstract double getValue();

    /**
     * Returns the unit in which this measure taker computes its results.
     *
     * @return the unit of this meter
     */
    public abstract String getUnit();

    /**
     * The long description of the unit. can be empty but if available, it should provide one or two words about the
     * measure taker.
     *
     * @return the long description of the unit in which measurement takes place.
     */
    public abstract String getUnitDescription();

    /**
     * A short name of the meter.
     *
     * @return the name.
     */
    public abstract String getName();

    /**
     * The String representation of this meter with its current value.
     *
     * @return a string representation of this meter.
     */
    @Override
    public final String toString() {

        return getName() + "[" + getUnit() + "]";
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public abstract int hashCode();

    /**
     * {@inheritDoc}
     */
    @Override
    public abstract boolean equals(final Object obj);

}
src/main/java/org/perfidix/AbstractConfig.java
public abstract class AbstractConfig {

    /**
     * Standard listeners
     */
    public final static Set<AbstractOutput> LISTENERS = new HashSet<AbstractOutput>();
    /**
     * Standard arrangement
     */
    protected final static KindOfArrangement ARRAN = KindOfArrangement.NoArrangement;
    /**
     * Standard gc-prob
     */
    protected final static double GARBAGE_PROB = 1d;
    /**
     * Standard runs
     */
    private final static int RUNS = 10;
    /**
     * Standard meters
     */
    private final static Set<AbstractMeter> METERS = new HashSet<AbstractMeter>();
    /**
     * actual value for runs
     */
    private transient final int runs;

    /**
     * actual value for meters
     */
    private transient final AbstractMeter[] meters;

    /**
     * actual value for listeners
     */
    private transient final AbstractOutput[] listeners;

    /**
     * actual value for runs
     */
    private transient final KindOfArrangement arrangement;

    /**
     * actual value for gcProb
     */
    private transient final double gcProb;

    static {
        METERS.add(new TimeMeter(Time.MilliSeconds));
    }

    /**
     * Simple constructor.
     * @param paramRuns runs of the benchmark
     * @param paramMeters meters to benchmark
     * @param paramOutput output of the benchmarks
     * @param paramArr arrangement of methods
     * @param paramGC prob of invoking the gc.
     */
    protected AbstractConfig(final int paramRuns, final Set<AbstractMeter> paramMeters, final Set<AbstractOutput> paramOutput, final KindOfArrangement paramArr, final double paramGC) {
        runs = paramRuns;

        meters = paramMeters.toArray(new AbstractMeter[paramMeters.size()]);
        listeners = paramOutput.toArray(new AbstractOutput[paramOutput.size()]);

        arrangement = paramArr;
        gcProb = paramGC;
    }

    /**
     * Getter for member meters
     *
     * @return the meters
     */
    public final AbstractMeter[] getMeters() {
        final AbstractMeter[] returnVal = new AbstractMeter[meters.length];
        System.arraycopy(meters, 0, returnVal, 0, returnVal.length);
        return returnVal;
    }

    /**
     * Getter for member runs
     *
     * @return the runs
     */
    public final int getRuns() {
        return runs;
    }

    /**
     * Getter for member gcProb
     *
     * @return the gcProb
     */
    public final double getGcProb() {
        return gcProb;
    }

    /**
     * Getter for member listeners
     *
     * @return the listeners
     */
    public final AbstractOutput[] getListener() {
        final AbstractOutput[] returnVal = new AbstractOutput[listeners.length];
        System.arraycopy(listeners, 0, returnVal, 0, returnVal.length);
        return returnVal;
    }

    /**
     * Getter for member arrangement
     *
     * @return the arrangement
     */
    public final KindOfArrangement getArrangement() {
        return arrangement;
    }

    /**
     * Standard config.
     *
     * @author Sebastian Graf, University of Konstanz
     */
    public static class StandardConfig extends AbstractConfig {

        /**
         * Constructor.
         */
        public StandardConfig() {
            super(RUNS, METERS, LISTENERS, ARRAN, GARBAGE_PROB);
        }

    }
}
src/main/java/org/perfidix/result/BenchmarkResult.java
public final class BenchmarkResult extends AbstractResultContainer<ClassResult> {

    /**
     * All occured exceptions.
     */
    private transient final Set<AbstractPerfidixMethodException> exceptions;

    /**
     * Outputs for listeners.
     */
    private transient final AbstractOutput[] outputs;

    /**
     * Constructor.
     *
     * @param paramOutputs {@link AbstractOutput} instances for listener
     */
    public BenchmarkResult(final AbstractOutput... paramOutputs) {
        super(null);
        this.exceptions = new HashSet<AbstractPerfidixMethodException>();
        outputs = paramOutputs;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getElementName() {
        return "Benchmark";
    }

    /**
     * Adding a dataset to a given meter and adapting the underlaying result model.
     *
     * @param meth  where the result is corresponding to
     * @param meter where the result is corresponding to
     * @param data  the data itself
     */
    public void addData(final BenchmarkMethod meth, final AbstractMeter meter, final double data) {

        final Class<?> clazz = meth.getMethodToBench().getDeclaringClass();
        if (!elements.containsKey(clazz)) {
            elements.put(clazz, new ClassResult(clazz));
        }

        final ClassResult clazzResult = elements.get(clazz);

        if (!clazzResult.elements.containsKey(meth)) {
            clazzResult.elements.put(meth, new MethodResult(meth));
        }

        final MethodResult methodResult = clazzResult.elements.get(meth);
        methodResult.addData(meter, data);
        clazzResult.addData(meter, data);
        this.addData(meter, data);

        for (final AbstractOutput output : outputs) {
            output.listenToResultSet(meth, meter, data);
        }

    }

    /**
     * Adding an exception to this result.
     *
     * @param exec the exception stored to this result
     */
    public void addException(final AbstractPerfidixMethodException exec) {
        this.getExceptions().add(exec);
        for (final AbstractOutput output : outputs) {
            output.listenToException(exec);
        }
    }

    /**
     * Getter for member exceptions.
     *
     * @return the exceptions
     */
    public Set<AbstractPerfidixMethodException> getExceptions() {
        return exceptions;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return super.toString() + "\nexceptions: " + getExceptions();
    }

}


Question: import org.perfidix.AbstractConfig;
import org.perfidix.Benchmark;
import org.perfidix.Perfidix;
import org.perfidix.element.BenchmarkMethod;
import org.perfidix.exceptions.PerfidixMethodCheckException;
import org.perfidix.exceptions.SocketViewException;
import org.perfidix.meter.AbstractMeter;
import org.perfidix.ouput.AbstractOutput;
import org.perfidix.ouput.TabularSummaryOutput;
import org.perfidix.result.BenchmarkResult;
import java.util.*;
/**
 * Copyright (c) 2012, University of Konstanz, Distributed Systems Group All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 * following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation and/or other materials provided with the
 * distribution. * Neither the name of the University of Konstanz nor the names of its contributors may be used to
 * endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.perfidix.socketadapter;



/**
 * The SocketAdapter is the main-class for registration of the classes that will
 * be benched and creation of the socket stub to the ide view.
 *
 * @author Lukas Lewandowski, University of Konstanz
 * @author Sebastian Graf, University of Konstanz
 */
public final class SocketAdapter {

	/**
	 * View instance for communicating with the perclipse plugin
	 */
	private transient final IUpdater view;
	/**
	 * Instance for this run of the adapter
	 */
	private transient Benchmark benchmark;

	/**
	 * Public constructor.
	 *
	 * @param update
	 *            updater for this output
	 * @param classes
	 *            to be benchmarked
	 * @throws IllegalAccessException
	 *             if communication with socket fails
	 * @throws InstantiationException
	 *             if initiation fails
	 * @throws ClassNotFoundException
	 *             if class is not found
	 * @throws SocketViewException
	 *             if socket communication fails
	 */
	public SocketAdapter(final IUpdater update, final String... classes)
			throws SocketViewException, ClassNotFoundException,
			InstantiationException, IllegalAccessException {
		view = update;

		// config adaptions for including the view
		final AbstractConfig oldConf = Perfidix.getConfiguration(classes);
		final AbstractOutput[] outputs = new AbstractOutput[oldConf
				.getListener().length + 1];
		System.arraycopy(oldConf.getListener(), 0, outputs, 0,
				oldConf.getListener().length);
		outputs[outputs.length - 1] = new SocketListener(view);

		Set<AbstractMeter> meters = new HashSet<AbstractMeter>();
		meters.addAll(Arrays.asList(oldConf.getMeters()));

		Set<AbstractOutput> listeners = new HashSet<AbstractOutput>();
		listeners.addAll(Arrays.asList(outputs));

		// Building up the benchmark object
		final AbstractConfig newConf = new AbstractConfig(oldConf.getRuns(),
				meters, listeners, oldConf.getArrangement(),
				oldConf.getGcProb()) {
		};
		benchmark = new Benchmark(newConf);

	}

	/**
	 * Main method for invoking benchs with classes as strings.
	 *
	 * @param args
	 *            the classes
	 */
	public static void main(final String[] args) {
		// init of the connection to the plugin
		int viewPort = 0;
		final List<String> classList = new ArrayList<String>();
		for (int i = 0; i < args.length; i++) {
			if (args[i].equals("-Port")) {
				if (args[i + 1] != null) {
					viewPort = Integer.parseInt(args[i + 1]);
				}
				break;
			} else {
				classList.add(args[i]);
			}
		}
		try {

			final IUpdater updater = new SocketViewProgressUpdater(null,
					viewPort);

			final SocketAdapter adapter = new SocketAdapter(updater,
					classList.toArray(new String[classList.size()]));

			adapter.registerClasses(classList.toArray(new String[classList
					.size()]));
			adapter.runBenchmark();
		} catch (final SocketViewException | ClassNotFoundException
				| InstantiationException | IllegalAccessException e) {
			throw new IllegalStateException(e);
		}
	}

	/**
	 * Registering all classes and getting a mapping with the Methods and the
	 * corresponding overall runs
	 *
	 * @param classNames
	 *            the names of the classes to be benched
	 * @throws SocketViewException
	 *             exception if socket communication fails
	 * @return if register succeeds or not
	 */
	public boolean registerClasses(final String... classNames)
			throws SocketViewException {
		try {
			benchmark = Perfidix.setUpBenchmark(classNames, benchmark);

			final Map<BenchmarkMethod, Integer> vals = benchmark
					.getNumberOfMethodsAndRuns();
			return view.initProgressView(vals);
Answer: 		} catch (final ClassNotFoundException | PerfidixMethodCheckException e2) {