code: package xyz.lejon.utils;
  
  import java.io.BufferedReader;
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.FileWriter;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.PrintWriter;
  import java.lang.management.ManagementFactory;
  import java.lang.management.RuntimeMXBean;
  import java.net.URL;
  import java.text.SimpleDateFormat;
  import java.util.ArrayList;
  import java.util.Date;
  import java.util.Enumeration;
  import java.util.List;
  import java.util.jar.Attributes;
  import java.util.jar.JarFile;
  import java.util.jar.Manifest;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
  import cc.mallet.util.Timing;
  import xyz.lejon.configuration.CommandLineParserUtil;
  import xyz.lejon.configuration.Configuration;
  
  public class LoggingUtils {
  
  	String baseDir = "";
  	File currentLogDirf = null;
  	private List<Timing> timings = new ArrayList<Timing>();
  
  	public synchronized File getLogDir() {
  		if(currentLogDirf==null) throw new IllegalArgumentException("You havent initialized the Logger before usage");
  		return currentLogDirf;
  	}
  
  	public synchronized File checkAndCreateCurrentLogDir(String dirPrefix) {
  		if(currentLogDirf==null) {
  			currentLogDirf = LoggingUtils.createLogDir(dirPrefix);
  			baseDir = currentLogDirf.getAbsolutePath();
  			return currentLogDirf;
  		} else {
  			return currentLogDirf;
  		}
  	}
  	
  	public static synchronized File checkCreateAndCreateDir(String string) {
  		File sublogdirf = new File(string);
  		if(!sublogdirf.exists()) {
  			sublogdirf.mkdirs();
  			return sublogdirf;
  		} else {
  			return sublogdirf;
  		}
  	}
  
  	public static synchronized PrintWriter checkCreateAndCreateLogPrinter(String dir,String filename) {
  		File sublogdirf = new File(dir);
  		if(!sublogdirf.exists()) {
  			sublogdirf.mkdirs();
  		} 
  		File logfile = new File(sublogdirf.getAbsolutePath() + "/" + filename);
  		try {
  			return new PrintWriter(new FileWriter(logfile,true));
  		} catch (IOException e) {
  			e.printStackTrace();
  			throw new IllegalArgumentException(e);
  		}
  	}
  
  	public synchronized File checkCreateAndSetSubLogDir(String string) {
  		if(!string.trim().equalsIgnoreCase("") && !string.trim().startsWith("/")) {
  			string = "/" + string;
  		}
  		File sublogdirf = new File(baseDir + string);
  		currentLogDirf = sublogdirf;
  		if(!sublogdirf.exists()) {
  			sublogdirf.mkdirs();
  			return sublogdirf;
  		} else {
  			return sublogdirf;
  		}
  	}
  
  	static File createLogDir(String pathPrefix) {
  		String dateFormatted = getDateStamp();
  		String logdir_base = pathPrefix + "/Run" + dateFormatted;
  		String logdir = logdir_base;
  
  		File logdirf = new File(logdir);
  		int trycnt = 1;
  		while( logdirf.exists() ) {
  			logdir = logdir_base + "_" + trycnt++;
  			logdirf = new File(logdir);
  		}
  		logdirf.mkdirs();
  		return logdirf;
  	}
  
  	public static String getDateStamp() {
  		Date logdate = new Date();
  		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd--HH_mm_ss");
  		return formatter.format(logdate);
  	}
  
  	public static String makeRunSuiteDir(String pathPrefix) {
  		String dateFormatted = getDateStamp();
  		String suiteNameBase = "RunSuite" + dateFormatted;
  		String logdir = pathPrefix + "/" + suiteNameBase;
  		File logdirf = new File(logdir);
  		int trycnt = 1;
  		while( logdirf.exists() ) {
  			logdir = pathPrefix + "/" + suiteNameBase + "_" + trycnt++;
  			logdirf = new File(logdir);
  		}
  		logdirf.mkdirs();
  
  		return suiteNameBase;
  	}
  
  	public static String makeRunSuiteDir(String pathPrefix, String suitePrefix) {
  		String dateFormatted = getDateStamp();
  		String suiteNameBase = suitePrefix + dateFormatted;
  		String logdir = pathPrefix + "/" + suiteNameBase;
  		File logdirf = new File(logdir);
  		int trycnt = 1;
  		while( logdirf.exists() ) {
  			logdir = pathPrefix + "/" + suiteNameBase + "_" + trycnt++;
  			logdirf = new File(logdir);
  		}
  		logdirf.mkdirs();
  
  		return suiteNameBase;
  	}
  
  	public void logTiming(Timing timeing) {
  		timings.add(timeing);
  	}
  
  	public void clearTimings() {
  		timings.clear();
  	}
  
  	public String dynamicLogRun(String pathPrefix, Timer t, 
  			CommandLineParserUtil cp, Configuration config, 
  			List<Long> memusage, String runner, 
  			String logfilename, String heading, String iterationType, int iterations,
  			List<String> metadata) throws Exception {
  
  		File logdirf = checkAndCreateCurrentLogDir(pathPrefix);
  		String logdir = logdirf.getAbsolutePath();
  		// Fix this tomorrow... ;)
  		//logTimings("Timings",logdir);
  
  		return doLogging(t, cp, config, memusage, runner,
  				logfilename, heading, iterationType, iterations, metadata,
  				logdir);
  	}
  
  	public static String getCommitHash() throws IOException {
  		ProcessBuilder pb = new ProcessBuilder("git", "rev-parse", "--verify", "HEAD");
  		/*Map<String, String> env = pb.environment();
  		 env.put("VAR1", "myValue");
  		 env.remove("OTHERVAR");
  		 env.put("VAR2", env.get("VAR1") + "suffix");*/
  		pb.directory(new File("."));
  		Process proc = pb.start();
  
  		BufferedReader stdInput = new BufferedReader(new 
  				InputStreamReader(proc.getInputStream()));
  
  		BufferedReader stdError = new BufferedReader(new 
  				InputStreamReader(proc.getErrorStream()));
  
  		String result = "";
  		String s = null;
  		while ((s = stdInput.readLine()) != null) {
  			result += s;
  		}
  
  		String err = "";
  		while ((s = stdError.readLine()) != null) {
  			err+=s;
  		}
  		
  		if(!err.equals("")) {
  			System.out.println("Here is the standard error of the command (if any):\n");
  			System.out.println(err);
  		}
  		return result;
  	}
  	
  	public static String getCommitComment(String hash) throws IOException {
  		ProcessBuilder pb = new ProcessBuilder("git", "log", "--max-count=1", "--pretty=oneline", hash);
  		/*Map<String, String> env = pb.environment();
  		 env.put("VAR1", "myValue");
  		 env.remove("OTHERVAR");
  		 env.put("VAR2", env.get("VAR1") + "suffix");*/
  		pb.directory(new File("."));
  		Process proc = pb.start();
  
  		BufferedReader stdInput = new BufferedReader(new 
  				InputStreamReader(proc.getInputStream()));
  
  		BufferedReader stdError = new BufferedReader(new 
  				InputStreamReader(proc.getErrorStream()));
  
  		String result = "";
  		String s = null;
  		while ((s = stdInput.readLine()) != null) {
  			result += s;
  		}
  
  		String err = "";
  		while ((s = stdError.readLine()) != null) {
  			err+=s;
  		}
  		
  		if(!err.equals("")) {
  			System.out.println("Here is the standard error of the command (if any):\n");
  			System.out.println(err);
  		}
  		return result;
  	}
  	
  	public static String getLatestCommit() throws IOException {
  		ProcessBuilder pb = new ProcessBuilder("git", "log", "--max-count=1", "--pretty=oneline");
  		/*Map<String, String> env = pb.environment();
  		 env.put("VAR1", "myValue");
  		 env.remove("OTHERVAR");
  		 env.put("VAR2", env.get("VAR1") + "suffix");*/
  		pb.directory(new File("."));
  		Process proc = pb.start();
  
  		BufferedReader stdInput = new BufferedReader(new 
  				InputStreamReader(proc.getInputStream()));
  
  		BufferedReader stdError = new BufferedReader(new 
  				InputStreamReader(proc.getErrorStream()));
  
  		String result = "";
  		String s = null;
  		while ((s = stdInput.readLine()) != null) {
  			result += s;
  		}
  
  		String err = "";
  		while ((s = stdError.readLine()) != null) {
  			err+=s;
  		}
  		
  		if(!err.equals("")) {
  			System.out.println("Here is the standard error of the command (if any):\n");
  			System.out.println(err);
  		}
  		return result;
  	}
  
  	public static String logRun(String pathPrefix, Timer t, 
  			CommandLineParserUtil cp,Configuration config, 
  			List<Long> memusage, String runner, 
  			String logfilename, String heading, String iterationType, int iterations,
  			List<String> metadata) throws Exception {
  
  		File logdirf = createLogDir(pathPrefix);
  		String logdir = logdirf.getAbsolutePath();
  
  		return doLogging(t, cp, config, memusage, runner,
  				logfilename, heading, iterationType, iterations, metadata,
  				logdir);
  	}
  
  	private static String doLogging(Timer t,
  			CommandLineParserUtil cp, Configuration config,
  			List<Long> memusage, String runner,
  			String logfilename, String heading, String iterationType,
  			int iterations, List<String> metadata, String logdir)
  					throws FileNotFoundException, Exception, IOException {
  		RuntimeMXBean RuntimemxBean = ManagementFactory.getRuntimeMXBean();
  		List<String> arguments = RuntimemxBean.getInputArguments();
  
  		if(!logfilename.startsWith("/") || !logdir.endsWith("/")) {
  			logfilename = "/" + logfilename;
  		}
  
  		PrintWriter out = new PrintWriter(logdir + logfilename + ".txt");
  		out.println("=== Setup ===");
  		out.print("Java Args:");
  		for( String arg : arguments ) {
  			out.print(arg + " ");
  		}
  		out.println();
  		if( cp != null) {
  			out.println("CommandLine: " + cp);
  			if(cp.getComment()!=null) out.println("Comment: " + cp.getComment());
  		}
  		if( config != null) { 
  			out.println("Active subconfig: " +config.getActiveSubConfig());
  			out.println("Config:Title: " + config.getStringProperty("title").trim());
  			out.println("Config:Description: " + config.getStringProperty("description").trim());
  		}
  		//out.println(iterationType + iterations);
  		out.println("Running class: " + runner);
  		out.println("=== Metadata ===");
  		
  		String implVer = getManifestInfo("Implementation-Version", "DOLDA");
  		String buildVer = getManifestInfo("Implementation-Build","DOLDA");
  		
  		if(implVer==null||buildVer==null) {
  			out.println("Latest Commit Info:" + getLatestCommit());						
  		} else {
  			out.println("Implementation-Version:" + implVer);
  			out.println("Implementation-Build:" + buildVer);			
  		}
  
  		if(metadata!=null) {
  			for( String meta : metadata ) {
  				out.println(meta);
  			}
  		}
  
  		if( config != null) { 
  			File confsrc = new File(config.whereAmI());
  			FileUtils.copyFile(new File(config.whereAmI()), new File(logdir + "/" + confsrc.getName()));
  		}
  
  		if(t!=null) {
  			t.stop();
  			out.println("Start: " + t.getStartdate());
  			out.println("Stop : " + t.getEnddate());
  		}
  		out.print("Memory Usage:");
  		if( memusage != null) {
  			for( Long mem : memusage ) {
  				out.print(mem/1000000000 + "Gb, ");
  			}
  		}
  		out.flush();
  		out.close();
  
  		return logdir + logfilename;
  	}
  	
  	public static String doInitialLogging(CommandLineParserUtil cp, Configuration config,
  			String runner, String logfilename,  List<String> metadata, String logdir)
  					throws FileNotFoundException, Exception, IOException {
  		
  		RuntimeMXBean RuntimemxBean = ManagementFactory.getRuntimeMXBean();
  		List<String> arguments = RuntimemxBean.getInputArguments();
  
  		if(!logfilename.startsWith("/") || !logdir.endsWith("/")) {
  			logfilename = "/" + logfilename;
  		}
  		
  		PrintWriter out = new PrintWriter(logdir + logfilename + ".txt");
  		out.println("=== Setup ===");
  		out.print("Java Args:");
  		for( String arg : arguments ) {
  			out.print(arg + " ");
  		}
  		out.println();
  		if( cp != null) {
  			out.println("CommandLine: " + cp);
  			if(cp.getComment()!=null) out.println("Comment: " + cp.getComment());
  		}
  		if( config != null) { 
  			out.println("Active subconfig: " +config.getActiveSubConfig());
  			out.println("Config:Title: " + config.getStringProperty("title").trim());
  			out.println("Config:Description: " + config.getStringProperty("description").trim());
  		}
  		//out.println(iterationType + iterations);
  		out.println("Running class: " + runner);
  		out.println("=== Metadata ===");
  		
  		String implVer = getManifestInfo("Implementation-Version", "DOLDA");
  		String buildVer = getManifestInfo("Implementation-Build","DOLDA");
  		
  		if(implVer==null||buildVer==null) {
  			out.println("Latest Commit Info:" + getLatestCommit());						
  		} else {
  			out.println("Implementation-Version:" + implVer);
  			out.println("Implementation-Build:" + buildVer);			
  		}
  
  		if(metadata!=null) {
  			for( String meta : metadata ) {
  				out.println(meta);
  			}
  		}
  
  		if( config != null) { 
  			File confsrc = new File(config.whereAmI());
  			FileUtils.copyFile(new File(config.whereAmI()), new File(logdir + "/" + confsrc.getName()));
  		}
  		
  		out.flush();
  		out.close();
  
  		return logdir + logfilename;
  	}
  
  	public static String getManifestInfo(String value, String jarfilePrefix) {
  		@SuppressWarnings("rawtypes")
  		Enumeration resEnum;
  		try {
  			resEnum = Thread.currentThread().getContextClassLoader().getResources(JarFile.MANIFEST_NAME);
  			while (resEnum.hasMoreElements()) {
  				try {
  					URL url = (URL)resEnum.nextElement();
  					Pattern p = Pattern.compile(jarfilePrefix + ".+\\.jar");
  					Matcher m = p.matcher(url.toExternalForm());	
  					if( m.find() ) {
  						InputStream is = url.openStream();
  						if (is != null) {
  							Manifest manifest = new Manifest(is);
  							Attributes mainAttribs = manifest.getMainAttributes();
  							String version = mainAttribs.getValue(value);
  							if(version != null) {
  								return version;
  							}
  						}
  					}
  				}
  				catch (Exception e) {
  				}
  			}
  		} catch (IOException e1) {
  		}
  		return null;
  	}
  
  	public String getBaseDir() {
  		return baseDir;
  	}
  
  	public List<Timing> getTimings() {
  		return timings;
  	}
  
  }
  