package fr.inria.diversify.logger.logger; import java.io.*; import java.util.*; public class LogWriter { private boolean fullPath = false; private PrintWriter fileWriter; private Map<Class, ClassObserver> classesObservers; private boolean isObserve = false; private boolean logMethodCall = true; private boolean writeVar = true; //Thread containing the test private final Thread thread; //current deep in the heap private int deep; private PathBuilder pathBuilder; ///Directory where the log is being stored protected File dir = null; ///Previous logs of variables status. Useful to validate whether they have change // protected Map<String, String> previousVars; /** * Constructor for the logger */ public LogWriter(Thread thread) { if (dir == null) { initDir(); } initOptions(); // previousVars = new HashMap<String, String>(); pathBuilder = new PathBuilder(fullPath); classesObservers = new HashMap<Class, ClassObserver>(); ShutdownHookLog shutdownHook = new ShutdownHookLog(); Runtime.getRuntime().addShutdownHook(shutdownHook); this.thread = thread; } protected void initOptions() { try { File propertiesFile = new File(dir.getAbsolutePath() + "/options"); if(propertiesFile.exists()) { Properties properties = new Properties(); properties.load(new FileInputStream(propertiesFile)); fullPath = Boolean.parseBoolean((String) properties.getOrDefault("fullPath", "false")); logMethodCall = Boolean.parseBoolean((String) properties.getOrDefault("logMethodCall", "true")); writeVar = Boolean.parseBoolean((String) properties.getOrDefault("writeVar", "true")); } } catch (IOException e) { System.err.println("fr.inria.logger: error with properties file"); } } /** * Gets the loggin path for the current thread * * @param thread Thread to log * @return The path with the log file */ public String getThreadLogFilePath(Thread thread) { return dir.getAbsolutePath() + "/" + getThreadFileName(thread); } public void close(){ fileWriter.append(KeyWord.endLine); fileWriter.close(); } /** * Initializes the directory where the files for each thread are going to be stored */ protected void initDir() { String logDirName = "log"; dir = new File(logDirName); while (!isLogDir(dir)) { logDirName = "../" + logDirName; dir = new File(logDirName); } } protected boolean isLogDir(File dir) { if(dir.exists()) { for(File fileInDir : dir.listFiles()) { if(fileInDir.getName().equals("info")) { return true; } } } return false; } /** * Returns the file name of the file where this thread's log is being stored * * @param thread * @return Relative filename of the file where this thread's log is being stored */ protected String getThreadFileName(Thread thread) { return "log" + thread.getName(); } //Thread containing the test public Thread getThread() { return thread; } public void branch(String id) { if(!isObserve) { pathBuilder.addbranch(id); } } public void methodIn(String methodId) { if(!isObserve) { deep++; if(logMethodCall) { try { PrintWriter fileWriter = getFileWriter(); fileWriter.append(KeyWord.endLine); fileWriter.append(KeyWord.methodCallObservation); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(deep + ""); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(methodId); } catch (Exception e) { e.printStackTrace(); } } pathBuilder.newPath(); } } public void methodOut(String id) { if(!isObserve) { try { pathBuilder.printPath(id, deep, getFileWriter()); } catch (Exception e) {} deep--; } } public void writeTestStart(String testName, Object receiver) { if(!isObserve) { try { deep = 0; PrintWriter fileWriter = getFileWriter(); fileWriter.append(KeyWord.endLine); fileWriter.append(KeyWord.testStartObservation); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(receiver.getClass().getCanonicalName()); fileWriter.append("."); fileWriter.append(testName); } catch (Exception e) { } } } public void writeTestStart(String testName) { if(!isObserve) { try { PrintWriter fileWriter = getFileWriter(); fileWriter.append(KeyWord.endLine); fileWriter.append(testName); } catch (Exception e) { } } } public void writeTestFinish() { if(!isObserve) { try { pathBuilder.clear(); PrintWriter fileWriter = getFileWriter(); fileWriter.append(KeyWord.endLine); fileWriter.append(KeyWord.testEndObservation); } catch (Exception e) { } } } public void writeVar(String methodId, Object... var) { if(!isObserve && writeVar) { isObserve = true; try { StringBuilder string = new StringBuilder(); string.append(KeyWord.endLine); string.append(KeyWord.variableObservation); string.append(KeyWord.simpleSeparator); string.append(deep + ""); string.append(KeyWord.simpleSeparator); string.append(methodId); // string.append(KeyWord.simpleSeparator); // string.append(localPositionId); String varsString = buildVars(var); if(varsString.isEmpty()) return; string.append(varsString); PrintWriter fileWriter = getFileWriter(); fileWriter.append(string.toString()); } catch (Exception e) { e.printStackTrace(); } finally { isObserve = false; } } } protected String buildVars(Object[] vars) { StringBuilder varsString = new StringBuilder(); for (int i = 0; i < vars.length / 2; i = i + 2) { try { String varName = vars[i].toString(); String value; if (vars[i + 1] == null) { value = "null"; } else { value = vars[i + 1].toString(); } if(value.length() > 1000) { value = vars[i + 1].getClass().getCanonicalName() + value.length(); } // String varId = positionId + ":" + varName; // String previousValue = previousVars.get(varId); // if (!value.equals(previousValue)) { // previousVars.put(varId, value); varsString.append(KeyWord.separator); varsString.append(varName); varsString.append(KeyWord.separator); varsString.append(value); // } } catch (Exception e) { } } return KeyWord.simpleSeparator + varsString.substring(KeyWord.separator.length(), varsString.length()); } public void logAssertArgument(int idAssertTarget, Object target, int idAssertInvocation, Object invocation) { logAssertArgument(idAssertTarget, target); logAssertArgument(idAssertInvocation, invocation); } public void logAssertArgument(int idAssert, Object invocation) { if(!isObserve) { isObserve = true; try { StringBuilder string = new StringBuilder(); string.append(KeyWord.endLine); string.append(KeyWord.assertObservation); string.append(KeyWord.simpleSeparator); string.append(idAssert + ""); PrintWriter fileWriter = getFileWriter(); string.append(KeyWord.simpleSeparator); observe(invocation, fileWriter); fileWriter.append(string.toString()); } catch (Exception e) { e.printStackTrace(); } finally { isObserve = false; } } } protected void observe(Object object, PrintWriter writer) throws IOException, InterruptedException { Class objectClass; if(object == null) { objectClass = null; } else { objectClass = object.getClass(); } if(!classesObservers.containsKey(objectClass)) { classesObservers.put(objectClass, new ClassObserver(objectClass)); } classesObservers.get(objectClass).observe(object,writer); } protected synchronized PrintWriter getFileWriter() throws IOException, InterruptedException { if (fileWriter == null) { String fileName = getThreadLogFilePath(thread) + "_" + System.currentTimeMillis(); fileWriter = new PrintWriter(new BufferedWriter(new FileWriter(fileName))); } return fileWriter; } public void writeCatch(String methodId, String localPositionId, Object exception) { if(!isObserve) { isObserve = true; try { PrintWriter fileWriter = getFileWriter(); fileWriter.append(KeyWord.endLine); fileWriter.append(KeyWord.catchObservation); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(deep + ""); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(methodId); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(localPositionId); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(exception.getClass().getCanonicalName()); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(exception.toString()); } catch (Exception e) { e.printStackTrace(); } finally { isObserve = false; } } } public void writeThrow(String methodId, String localPositionId, Object exception) { if(!isObserve) { isObserve = true; try { PrintWriter fileWriter = getFileWriter(); fileWriter.append(KeyWord.endLine); fileWriter.append(KeyWord.throwObservation); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(deep + ""); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(methodId); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(localPositionId); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(exception.getClass().getCanonicalName()); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(exception.toString()); } catch (Exception e) { e.printStackTrace(); } finally { isObserve = false; } } } public void logTransformation(String id) { if (!isObserve) { try { System.out.println("log transformation: "+id); PrintWriter fileWriter = getFileWriter(); fileWriter.append(KeyWord.endLine); fileWriter.append(KeyWord.logTransformation); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(deep + ""); fileWriter.append(KeyWord.simpleSeparator); fileWriter.append(id); } catch (Exception e) { } } } }