All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sqlapp.graphviz.command.DotRuntime Maven / Gradle / Ivy

There is a newer version: 0.12.37
Show newest version
/**
 * Copyright (C) 2007-2017 Tatsuo Satoh 
 *
 * This file is part of sqlapp-graphviz.
 *
 * sqlapp-graphviz is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * sqlapp-graphviz is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with sqlapp-graphviz.  If not, see .
 */

package com.sqlapp.graphviz.command;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.sqlapp.util.CommonUtils;
import com.sqlapp.util.FileUtils;

public class DotRuntime {

	private static final String LINE_SEPARATOR=System.getProperty("file.separator");
	
	private static final boolean WIN32 = "\\".equals(LINE_SEPARATOR);
	
    private String dot;
	
	private File dir=new File("./");
	
	private OutputFormat outputFormat=OutputFormat.png;

	private final ExecutorService executorService;
	
	public DotRuntime(){
		executorService=Executors.newCachedThreadPool(new ThreadFactory(){
			@Override
			public Thread newThread(Runnable arg0) {
				Thread thread=new Thread(arg0);
				thread.setDaemon(true);
				return thread;
			}
		});
	}

	public String execute(String dotFile, String diagramFile){
		Process process;
		List commandList=new ArrayList<>();
		try {
			commandList.add(getDotExe());
			commandList.add("-T" + getOutputFormat());
			commandList.add(dotFile);
			commandList.add("-o" + diagramFile);
			commandList.add("-Tcmapx");
			//commandList.add("-Timap");
			process = Runtime.getRuntime().exec(commandList.toArray(new String[0]), null, dir);
			ThreadReader threadReader=new ThreadReader(process.getInputStream());
			ThreadReader errorThreadReader=new ThreadReader(process.getErrorStream());
			Future future1=executorService.submit(threadReader);
			Future future2=executorService.submit(errorThreadReader);
			int ret = process.waitFor();
			if (ret == 0){
				future1.get();
				return threadReader.getResult();
			} else{
				future2.get();
				throw new DotCommandException(ret, errorThreadReader.getResult());
			}
		} catch (IOException e) {
			throw new DotRuntimeException(e);
		} catch (InterruptedException e) {
			throw new DotRuntimeException(e);
		} catch (ExecutionException e) {
			throw new DotRuntimeException(e);
		}
	}
	
	private static final Pattern DOT_VERSION_PATTERN=Pattern.compile("dot.*\\s+version\\s+(\\S+).*");
	
	public String getVersion(){
		Process process;
		List commandList=new ArrayList<>();
		try {
			commandList.add(getDotExe());
			commandList.add("-V");
			process = Runtime.getRuntime().exec(commandList.toArray(new String[0]));
			ThreadReader threadReader=new ThreadReader(process.getInputStream());
			ThreadReader errorThreadReader=new ThreadReader(process.getErrorStream());
			Future future=executorService.submit(threadReader);
			Future futureError=executorService.submit(errorThreadReader);
			int ret = process.waitFor();
			if (ret == 0){
				futureError.get();
				future.cancel(true);
				String version=errorThreadReader.getResult();
				Matcher matcher=DOT_VERSION_PATTERN.matcher(version);
				if (matcher.matches()){
					return matcher.group(1);
				}
				return null;
			} else{
				return null;
			}
		} catch (IOException e) {
			throw new DotRuntimeException(e);
		} catch (InterruptedException e) {
			throw new DotRuntimeException(e);
		} catch (ExecutionException e) {
			throw new DotRuntimeException(e);
		}
	}
	
	static class ThreadReader implements Runnable{

		private final InputStream is;
		
		private BufferedReader bufReader;
		private StringBuilder builder=new StringBuilder();
		
		ThreadReader(InputStream is){
			this.is=is;
			bufReader = new BufferedReader(new InputStreamReader(is));
		}
		
		@Override
		public void run() {
			String line;
			try {
				while ((line = bufReader.readLine()) != null) {
					builder.append(line);
					builder.append(LINE_SEPARATOR);
				}
			} catch (IOException e) {
				throw new DotRuntimeException(e);
			} finally{
				FileUtils.close(bufReader);
				FileUtils.close(is);
			}
		}

		public String getResult(){
			return builder.toString();
		}
		
	}
	
	
	private String getDotExe(){
		if (WIN32){
			File file=getWin32GraphvizPath();
			if (file==null){
				return dot!=null?dot:"dot";
			}
			return file.getAbsolutePath();
		} else{
			return dot!=null?dot:"dot";
		}
	}

	private File getWin32GraphvizPath(){
		String programFiles=System.getenv("ProgramFiles");
		File programFilesPath=new File(programFiles);
		File graphvizDirecroty=getWin32GraphvizDirectoryFromProgramFiles(programFilesPath);
		if (graphvizDirecroty==null){
			graphvizDirecroty=getWin32GraphvizDirectory(programFiles, programFilesPath);
		}
		if (graphvizDirecroty!=null){
			return new File(graphvizDirecroty, "bin"+System.getProperty("file.separator")+"dot.exe");
		}
		return null;
	}

	
	private File getWin32GraphvizDirectory(String programFiles, File programFilesPath){
		File programFilesPathParent=programFilesPath.getParentFile();
		File[] programFilesOthers=programFilesPathParent.listFiles(f->{
			return f.isDirectory()&&f.getAbsolutePath().startsWith(programFiles+" ");
		});
		if (programFilesOthers==null) {
			return null;
		}
		for(File programFilesOther:programFilesOthers){
			File graphvizDirecroty=getWin32GraphvizDirectoryFromProgramFiles(programFilesOther);
			if (graphvizDirecroty!=null){
				return graphvizDirecroty;
			}
		}
		return null;
	}
	
	private File getWin32GraphvizDirectoryFromProgramFiles(File programFilesPath){
		File[] files=programFilesPath.listFiles(f->{
			return f.isDirectory()&&f.getName().startsWith("Graphviz");
		});
		if (CommonUtils.isEmpty(files)){
			return null;
		}
		Arrays.sort(files);
		return files[files.length-1];
	}

	/**
	 * @return the dot
	 */
	public String getDot() {
		return dot;
	}

	/**
	 * @param dot the dot to set
	 */
	public void setDot(String dot) {
		this.dot = dot;
	}

	/**
	 * @return the dir
	 */
	public File getDir() {
		return dir;
	}

	/**
	 * @param dir the dir to set
	 */
	public void setDir(File dir) {
		this.dir = dir;
	}

	/**
	 * @return the outputFormat
	 */
	public OutputFormat getOutputFormat() {
		return outputFormat;
	}

	/**
	 * @param outputFormat the outputFormat to set
	 */
	public void setOutputFormat(OutputFormat outputFormat) {
		this.outputFormat = outputFormat;
	}
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy