content: /**
   * ﻿Copyright (C) 2007 - 2019 52°North Initiative for Geospatial Open Source
   * Software GmbH
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 as published
   * by the Free Software Foundation.
   *
   * If the program is linked with libraries which are licensed under one of
   * the following licenses, the combination of the program with the linked
   * library is not considered a "derivative work" of the program:
   *
   *       • Apache License, version 2.0
   *       • Apache Software License, version 1.0
   *       • GNU Lesser General Public License, version 3
   *       • Mozilla Public License, versions 1.0, 1.1 and 2.0
   *       • Common Development and Distribution License (CDDL), version 1.0
   *
   * Therefore the distribution of the program linked with libraries licensed
   * under the aforementioned licenses, is permitted by the copyright holders
   * if the distribution is compliant with both the GNU General Public
   * License version 2 and the aforementioned licenses.
   *
   * This program 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 General
   * Public License for more details.
   */
  package org.n52.wps.server.grass.io;
  
  import java.io.BufferedReader;
  import java.io.BufferedWriter;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.FileWriter;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.io.PipedInputStream;
  import java.io.PipedOutputStream;
  import java.net.InetAddress;
  import java.util.List;
  import java.util.Map;
  import java.util.UUID;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.n52.wps.commons.WPSConfig;
  import org.n52.wps.io.data.GenericFileDataWithGT;
  import org.n52.wps.io.data.GenericFileDataConstants;
  import org.n52.wps.io.data.IData;
  import org.n52.wps.io.data.binding.complex.GenericFileDataWithGTBinding;
  import org.n52.wps.server.WebProcessingService;
  import org.n52.wps.server.grass.GrassProcessRepository;
  import org.n52.wps.server.grass.util.JavaProcessStreamReader;
  
  /**
   * @author Benjamin Pross (bpross-52n)
   *
   */
  public class GrassIOHandler {
  	
  	private String grassHome;
  	private String pythonHome;	
  	private String pythonPath;	
  	private String grassModuleStarterHome;	
  	private String tmpDir;
  	private String inputTxtFilename;
  	private String command;	
  	private String systemBlock;
  	private String grassBlock;
  	private String complexInputDataBlock;
  	private String literalInputDataBlock;
  	private String outputDataBlock;	
  	private String uuid;	
  	private String pythonName = "python.exe";	
  	private String addonPath;	
  	private String[] envp;
  	private boolean isAddon;
  	private static Logger LOGGER = LoggerFactory.getLogger(GrassIOHandler.class);
  	
  	private final String logFilename = ".log";
  	private final String stdErrorFilename = "_stderr.log";
  	private final String stdOutFilename = "_stdout.log ";	
  	private final String fileSeparator = System.getProperty("file.separator");
  	private final String lineSeparator = System.getProperty("line.separator");
  	private final String appDataDir = System.getenv("APPDATA");
  	
  	public static final String GRASS_ADDON_PATH = "�addonPath�";	
  	public static final String PROCESS_IDENTIFIER = "�process_identifier�";
  	public static final String INPUT_IDENTIFIER = "�input_identifier�";
  	public static final String INPUT_PATH = "�input_path�";
  	public static final String DATA_TYPE = "�datatype�";
  	public static final String VALUE = "�value�";
  	public static final String OUTPUT_IDENTIFIER = "�output_identifier�";
  	public static final String OUTPUT_PATH = "�output_path�";
  	public static final String SCHEMA = "�schema�";
  	public static final String ENCODING = "�encoding�";
  	public static final String MIMETYPE = "�mimetype�";
  	public static final String WORKDIR = "�workdir�";
  	public static final String OUTPUTDIR = "�outputdir�";	
  	public static final String OS_Name = System.getProperty("os.name");
  	
  	public GrassIOHandler(){		
  		
  		if(!OS_Name.startsWith("Windows")){
  			pythonName = "python";	
  		}
  		
  		grassHome = GrassProcessRepository.grassHome;
  		grassModuleStarterHome = GrassProcessRepository.grassModuleStarterHome;
  		tmpDir = GrassProcessRepository.tmpDir;
  		pythonHome = GrassProcessRepository.pythonHome;
  		pythonPath = GrassProcessRepository.pythonPath;
  		addonPath = GrassProcessRepository.addonPath;
  
  		File tmpDirectory = new File(tmpDir);
  		
  		if(!tmpDirectory.exists()){
  			tmpDirectory.mkdir();
  		}
  	}	
  	
  	/**
  	 * Method to execute a GRASS GIS process.
  	 * 
  	 * @param processID the name of the process
  	 * @param complexInputData complex inputdata for the process
  	 * @param literalInputData literal inputdata for the process
  	 * @param outputID the ID of the output
  	 * @param outputMimeType the mimetype of the output
  	 * @param outputSchema the schema of the output
  	 * @return a GenericFileDataBinding containing the generated ouput
  	 */
  	public IData executeGrassProcess(String processID, Map<String, List<IData>> complexInputData, Map<String, List<IData>> literalInputData, String outputID, String outputMimeType, String outputSchema, boolean isAddon){
  		
  		String outputFileName = "";
  		
  		this.isAddon = isAddon;
  		
  		outputFileName = tmpDir + fileSeparator + "out" + UUID.randomUUID().toString().substring(0, 5) + "." + GenericFileDataConstants.mimeTypeFileTypeLUT().get(outputMimeType);
  		
  		boolean success = createInputTxt(processID, complexInputData, literalInputData, outputID, outputFileName, outputMimeType, outputSchema);
  		
  		if(!success){
  			inputTxtFilename = null;	
  			return null;
  		}
  		
  		//start grassmodulestarter.py 
  		executeGrassModuleStarter();
  		
  		File outputFile = new File(outputFileName);
  		
  		if(!outputFile.exists()){
  			inputTxtFilename = null;	
  			return null;
  		}
  		
  		//give back genericfiledatabinding with the outputfile created by grass
  		try {
  			
  			GenericFileDataWithGT outputFileData = new GenericFileDataWithGT(outputFile, outputMimeType);
  			
  			GenericFileDataWithGTBinding outputData = new GenericFileDataWithGTBinding(outputFileData);	
  			
  			return outputData;
  			
  		} catch (IOException e) {
  			e.printStackTrace();
  			
  			return null;
  		}finally{
  			inputTxtFilename = null;
  		}		
  	}
  	
  	private String getCommand() {
  		
  		if(command == null){
  			uuid = UUID.randomUUID().toString().substring(0, 7);
  			command  = getPythonHome() + fileSeparator + pythonName + " "
  			+ grassModuleStarterHome + fileSeparator + "GrassModuleStarter.py -f " + getInputTxtFilename() +" -l " + tmpDir + fileSeparator + uuid + logFilename + " -o " + tmpDir + fileSeparator + stdOutFilename + " -e " + tmpDir + fileSeparator + stdErrorFilename;
  		}
  		
  		return command;
  	}
  
  	private String[] getEnvp() {
  
  		if (envp == null) {
  
  			if (!OS_Name.startsWith("Windows")) {
  
  				envp = new String[] {
  						"GDAL_DATA=" + grassHome + fileSeparator + "etc"
  								+ fileSeparator + "ogr_csv",
  						"PATH=" + grassHome + fileSeparator + "lib:"
  								+ grassHome + fileSeparator + "bin:"
  								+ grassHome + fileSeparator + "scripts:"
  								+ pythonHome + ":" + grassHome + fileSeparator
  								+ "extralib:" + grassHome + fileSeparator
  								+ "extrabin",
  						"LD_LIBRARY_PATH=" + grassHome + fileSeparator + "lib",
  						"PWD=" + grassHome,
  						"PYTHONHOME=" + pythonHome,
  						"PYTHONPATH=" + grassHome + fileSeparator + "etc"
  								+ fileSeparator + "python" + ":" + pythonPath,
  						"GRASS_CONFIG_DIR=.grass7",
  						"GRASS_GNUPLOT=gnuplot -persist", "GRASS_PAGER=less",
  						"GRASS_PYTHON=python", "GRASS_SH=/bin/sh",
  						"GRASS_VERSION=7.0.svn"};		
  				
  			} else {
  
  				envp = new String[] {
  						"APPDATA=" + appDataDir,
  						"GDAL_DATA=" + grassHome + "\\etc\\ogr_csv",
  						"PWD=" + grassHome,
  //						"PATH=C:\\grass\\wps-grass-bridge2\\gms\\Testing\\Python\\GrassAddons;C:\\Programme\\GRASS-70-SVN\\lib;C:\\Programme\\GRASS-70-SVN\\bin;C:\\Programme\\GRASS-70-SVN\\scripts;C:\\OSGeo4W\\bin;",
  //						"PYTHONPATH=" + grassHome + "\\etc\\python;c:\\python25",
  //						"PYTHONHOME=C:\\OSGeo4W\\apps\\Python25",
  						"PYTHONHOME=" + pythonHome,
  						"GRASS_CONFIG_DIR=.grass7",
  						"GRASS_GNUPLOT=gnuplot -persist", "GRASS_PAGER=less",
  						"GRASS_PYTHON=python", "GRASS_SH=/bin/sh",
  						"GRASS_VERSION=7.0.svn", "SystemRoot=" + System.getenv("SystemRoot"),
  						"WINGISBASE=" + grassHome 
  						};				
  			}
  		}
  
  		return envp;
  	}
  
  	private String getInputTxtFilename() {
  		
  		if(inputTxtFilename == null){
  			
  			String txtID = UUID.randomUUID().toString();
  			
  			txtID = txtID.substring(0, 5);
  			
  			inputTxtFilename = tmpDir + fileSeparator + txtID + ".txt";
  		}
  		return inputTxtFilename;
  	}
  
  	private String getSystemBlock() {
  		if(systemBlock == null){
  			systemBlock = "[System]" + lineSeparator + " WorkDir=" + WORKDIR
  			+ lineSeparator + " OutputDir=" + OUTPUTDIR + lineSeparator;
  		}
  		return systemBlock;
  	}
  
  	private String getGrassBlock() {
  		if(grassBlock == null){
  			grassBlock = "[GRASS]"
  				+ lineSeparator
  				+ " GISBASE=" + grassHome
  				+ lineSeparator + " GRASS_ADDON_PATH=" + GRASS_ADDON_PATH  + lineSeparator + " GRASS_VERSION=7.0.svn"
  				+ lineSeparator + " Module=" + PROCESS_IDENTIFIER + lineSeparator + " LOCATION="
  				+ lineSeparator + " LinkInput=FALSE" + lineSeparator + " IgnoreProjection=FALSE"
  				+ lineSeparator + " UseXYLocation=FALSE" + lineSeparator;
  		}
  		return grassBlock;
  	}
  
  	private String getComplexInputDataBlock() {
  		if(complexInputDataBlock == null){
  			complexInputDataBlock  = "[ComplexData]" + lineSeparator
  			+ " Identifier=" + INPUT_IDENTIFIER + lineSeparator
  			+ " MaxOccurs=1" + lineSeparator
  			+ " PathToFile=" + INPUT_PATH + lineSeparator + " MimeType=" + MIMETYPE + lineSeparator
  			+ " Encoding=" + ENCODING + lineSeparator
  			+ " Schema=" + SCHEMA + lineSeparator;
  		}
  		return complexInputDataBlock;
  	}
  
  	private String getLiteralInputDataBlock() {
  		if(literalInputDataBlock == null){
  			literalInputDataBlock = "[LiteralData]" + lineSeparator
  			+ " Identifier=" + INPUT_IDENTIFIER + lineSeparator + " DataType=" + DATA_TYPE + lineSeparator
  			+ " Value=" + VALUE + lineSeparator;
  		}
  		return literalInputDataBlock;
  	}
  
  	private String getOutputDataBlock() {
  		if(outputDataBlock == null){
  			outputDataBlock = "[ComplexOutput]" + lineSeparator
  			+ " Identifier=" + OUTPUT_IDENTIFIER + lineSeparator
  			+ " PathToFile=" + OUTPUT_PATH + lineSeparator + " MimeType=" + MIMETYPE + lineSeparator
  			+ " Encoding=" + ENCODING + lineSeparator
  			+ " Schema=" + SCHEMA + lineSeparator;
  		}
  		return outputDataBlock;
  	}
  
  	private String getPythonHome() {
  		if(pythonHome == null){
  			pythonHome = grassHome + "\\extrabin";
  		}
  		return pythonHome;
  	}
  	
  	/**
  	 * Creates the txt-file required by the GrassModuleStarter.py
  	 * 
  	 * @param processID
  	 *            ID of the process
  	 * @param complexInputData
  	 *            complexinputdata for the process
  	 * @param literalInputData
  	 *            literalinputdata for the process
  	 * @param outputID
  	 *            ID of the outputdata
  	 * @param outputFileName
  	 *            name and path to the result of the GRASS-process
  	 * @param outputMimeType
  	 *            suggested mimetype of the result of the GRASS-process
  	 * @return true, if everything worked, otherwise false
  	 */
  	private boolean createInputTxt(String processID, Map<String, List<IData>> complexInputData, Map<String, List<IData>> literalInputData, String outputID, String outputFileName, String outputMimeType, String outputSchema){
  	
  		try {
  			
  			LOGGER.info("Creating input.txt.");
  			
  			BufferedWriter inputTxtWriter = new BufferedWriter(new FileWriter(new File(getInputTxtFilename())));
  			
  			String tmpBlock;
  			
  			tmpBlock = getSystemBlock().replace(WORKDIR, tmpDir);
  			tmpBlock = tmpBlock.replace(OUTPUTDIR, tmpDir);
  			
  			inputTxtWriter.write(tmpBlock);
  			inputTxtWriter.write(lineSeparator);
  			
  			tmpBlock  = getGrassBlock().replace(PROCESS_IDENTIFIER, processID); 
  			if(isAddon){
  				tmpBlock  = tmpBlock.replace(GRASS_ADDON_PATH, addonPath); 			
  			}else{				
  				tmpBlock  = tmpBlock.replace(GRASS_ADDON_PATH, ""); 			
  			}
  			
  			inputTxtWriter.write(tmpBlock);
  			inputTxtWriter.write(lineSeparator);
  			
  			for (String key : complexInputData.keySet()) {
  				
  				List<IData> dataList = complexInputData.get(key);
  				
  				for (IData data : dataList) {
  				
  				if(!(data instanceof GenericFileDataWithGTBinding)){
  					continue;
  				}
  				
  				String mimetype = ((GenericFileDataWithGTBinding)data).getPayload().getMimeType();
  				
  				if(mimetype.equals(GenericFileDataConstants.MIME_TYPE_TIFF)){					
  					tmpBlock = getComplexInputDataBlock().replace(MIMETYPE, mimetype);
  					tmpBlock = tmpBlock.replace(ENCODING, "");
  					tmpBlock = tmpBlock.replace(SCHEMA, "");
  				}else if( mimetype.equals(GenericFileDataConstants.MIME_TYPE_ZIPPED_SHP)){
  					tmpBlock = getComplexInputDataBlock().replace(MIMETYPE, "APPLICATION/SHP");
  					tmpBlock = tmpBlock.replace(ENCODING, "");
  					tmpBlock = tmpBlock.replace(SCHEMA, "");
  				}else if(mimetype.equals(GenericFileDataConstants.MIME_TYPE_PLAIN_TEXT)){
  					tmpBlock = getComplexInputDataBlock().replace(MIMETYPE, GenericFileDataConstants.MIME_TYPE_PLAIN_TEXT);
  					tmpBlock = tmpBlock.replace(ENCODING, "UTF-8");
  					tmpBlock = tmpBlock.replace(SCHEMA, "");
  				}else if(mimetype.equals(GenericFileDataConstants.MIME_TYPE_TEXT_XML)){
  					tmpBlock = getComplexInputDataBlock().replace(MIMETYPE, "TEXT/XML");
  					tmpBlock = tmpBlock.replace(ENCODING, "UTF-8");
  					tmpBlock = tmpBlock.replace(SCHEMA, "GML");
  				}else if(mimetype.equals(GenericFileDataConstants.MIME_TYPE_KML)){
  					tmpBlock = getComplexInputDataBlock().replace(MIMETYPE, "TEXT/XML");
  					tmpBlock = tmpBlock.replace(ENCODING, "UTF-8");
  					tmpBlock = tmpBlock.replace(SCHEMA, "KML");
  				}else if(mimetype.equals(GenericFileDataConstants.MIME_TYPE_IMAGE_PNG)){
  					tmpBlock = getComplexInputDataBlock().replace(MIMETYPE, "IMAGE/PNG");
  					tmpBlock = tmpBlock.replace(ENCODING, "");
  					tmpBlock = tmpBlock.replace(SCHEMA, "");
  				}else if(mimetype.equals(GenericFileDataConstants.MIME_TYPE_IMAGE_JPEG)){
  					tmpBlock = getComplexInputDataBlock().replace(MIMETYPE, "IMAGE/JPEG");
  					tmpBlock = tmpBlock.replace(ENCODING, "");
  					tmpBlock = tmpBlock.replace(SCHEMA, "");
  				}else if(mimetype.equals(GenericFileDataConstants.MIME_TYPE_IMAGE_GIF)){
  					tmpBlock = getComplexInputDataBlock().replace(MIMETYPE, "IMAGE/GIF");
  					tmpBlock = tmpBlock.replace(ENCODING, "");
  					tmpBlock = tmpBlock.replace(SCHEMA, "");
  				}else if(mimetype.equals(GenericFileDataConstants.MIME_TYPE_IMAGE_GEOTIFF)){
  					tmpBlock = getComplexInputDataBlock().replace(MIMETYPE, "IMAGE/GEOTIFF");
  					tmpBlock = tmpBlock.replace(ENCODING, "");
  					tmpBlock = tmpBlock.replace(SCHEMA, "");
  				}else if(mimetype.equals(GenericFileDataConstants.MIME_TYPE_HDF)){
  					tmpBlock = getComplexInputDataBlock().replace(MIMETYPE, "APPLICATION/HDF4Image");
  					tmpBlock = tmpBlock.replace(ENCODING, "");
  					tmpBlock = tmpBlock.replace(SCHEMA, "");
  				}else if(mimetype.equals(GenericFileDataConstants.MIME_TYPE_X_ERDAS_HFA)){
  					tmpBlock = getComplexInputDataBlock().replace(MIMETYPE, "APPLICATION/X-ERDAS-HFA");
  					tmpBlock = tmpBlock.replace(ENCODING, "");
  					tmpBlock = tmpBlock.replace(SCHEMA, "");
  				}else if(mimetype.equals(GenericFileDataConstants.MIME_TYPE_NETCDF)){
  					tmpBlock = getComplexInputDataBlock().replace(MIMETYPE, "APPLICATION/NETCDF");
  					tmpBlock = tmpBlock.replace(ENCODING, "");
  					tmpBlock = tmpBlock.replace(SCHEMA, "");
  				}else if(mimetype.equals(GenericFileDataConstants.MIME_TYPE_DGN)){
  					tmpBlock = getComplexInputDataBlock().replace(MIMETYPE, "APPLICATION/DGN");
  					tmpBlock = tmpBlock.replace(ENCODING, "");
  					tmpBlock = tmpBlock.replace(SCHEMA, "");
  				}					
  
  				String filename = ((GenericFileDataWithGTBinding)data).getPayload().getBaseFile(true).getAbsolutePath();
  				
  				tmpBlock = tmpBlock.replace(INPUT_IDENTIFIER, key);
  				tmpBlock = tmpBlock.replace(INPUT_PATH, filename);
  				
  				inputTxtWriter.write(tmpBlock);
  				inputTxtWriter.write(lineSeparator);
  				}
  			}
  			
  			for (String key : literalInputData.keySet()) {
  				
  				List<IData> dataList = literalInputData.get(key);
  				
  				for (IData data : dataList) {
  				
  				tmpBlock = getLiteralInputDataBlock().replace(INPUT_IDENTIFIER, key);
  				
  				Class<?> supportedClass = data.getSupportedClass();
  				
  				if(supportedClass.equals(Float.class)){
  					tmpBlock = tmpBlock.replace(DATA_TYPE, "float");
  				}else if(supportedClass.equals(Double.class)){
  					tmpBlock = tmpBlock.replace(DATA_TYPE, "double");
  				}else if(supportedClass.equals(Integer.class)){
  					tmpBlock = tmpBlock.replace(DATA_TYPE, "integer");
  				}else if(supportedClass.equals(Long.class)){
  					tmpBlock = tmpBlock.replace(DATA_TYPE, "integer");
  				}else if(supportedClass.equals(String.class)){
  					tmpBlock = tmpBlock.replace(DATA_TYPE, "string");
  				}else if(supportedClass.equals(Boolean.class)){
  					tmpBlock = tmpBlock.replace(DATA_TYPE, "boolean");
  				}
  				
  				tmpBlock = tmpBlock.replace(VALUE, String.valueOf(data.getPayload()));
  				
  				inputTxtWriter.write(tmpBlock);
  				inputTxtWriter.write(lineSeparator);
  				
  				}
  			}
  			
  			tmpBlock = getOutputDataBlock().replace(OUTPUT_IDENTIFIER, outputID);
  			tmpBlock = tmpBlock.replace(OUTPUT_PATH, outputFileName);
  			
  			if(outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_PLAIN_TEXT)){
  				tmpBlock = tmpBlock.replace(MIMETYPE, "text/plain");
  				tmpBlock = tmpBlock.replace(ENCODING, "");
  				tmpBlock = tmpBlock.replace(SCHEMA, "");				
  			}else if(outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_ZIPPED_SHP)){
  				tmpBlock = tmpBlock.replace(MIMETYPE, "APPLICATION/SHP");
  				tmpBlock = tmpBlock.replace(ENCODING, "");
  				tmpBlock = tmpBlock.replace(SCHEMA, "");
  			}else if(outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_TIFF) || outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_GEOTIFF)){
  				tmpBlock = tmpBlock.replace(MIMETYPE, GenericFileDataConstants.MIME_TYPE_TIFF);
  				tmpBlock = tmpBlock.replace(ENCODING, "");
  				tmpBlock = tmpBlock.replace(SCHEMA, "");
  			}else if(outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_TEXT_XML)){ 
  				tmpBlock = tmpBlock.replace(MIMETYPE, GenericFileDataConstants.MIME_TYPE_TEXT_XML);
  				tmpBlock = tmpBlock.replace(ENCODING, "UTF-8");
  				tmpBlock = tmpBlock.replace(SCHEMA, "http://schemas.opengis.net/gml/3.1.0/polygon.xsd");//TODO change to gml2.1.2?!
  			}else if(outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_KML)){
  				tmpBlock = tmpBlock.replace(MIMETYPE, "TEXT/XML");
  				tmpBlock = tmpBlock.replace(ENCODING, "UTF-8");
  				tmpBlock = tmpBlock.replace(SCHEMA, "KML");
  			}else if(outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_IMAGE_PNG)){
  				tmpBlock = tmpBlock.replace(MIMETYPE, "IMAGE/PNG");
  				tmpBlock = tmpBlock.replace(ENCODING, "");
  				tmpBlock = tmpBlock.replace(SCHEMA, "");
  			}else if(outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_IMAGE_JPEG)){
  				tmpBlock = tmpBlock.replace(MIMETYPE, "IMAGE/JPEG");
  				tmpBlock = tmpBlock.replace(ENCODING, "");
  				tmpBlock = tmpBlock.replace(SCHEMA, "");
  			}else if(outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_IMAGE_GIF)){
  				tmpBlock = tmpBlock.replace(MIMETYPE, "IMAGE/GIF");
  				tmpBlock = tmpBlock.replace(ENCODING, "");
  				tmpBlock = tmpBlock.replace(SCHEMA, "");
  			}else if(outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_IMAGE_GEOTIFF)){
  				tmpBlock = tmpBlock.replace(MIMETYPE, "IMAGE/GEOTIFF");
  				tmpBlock = tmpBlock.replace(ENCODING, "");
  				tmpBlock = tmpBlock.replace(SCHEMA, "");
  			}else if(outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_HDF)){
  				tmpBlock = tmpBlock.replace(MIMETYPE, "APPLICATION/HDF4Image");
  				tmpBlock = tmpBlock.replace(ENCODING, "");
  				tmpBlock = tmpBlock.replace(SCHEMA, "");
  			}else if(outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_X_ERDAS_HFA)){
  				tmpBlock = tmpBlock.replace(MIMETYPE, "APPLICATION/X-ERDAS-HFA");
  				tmpBlock = tmpBlock.replace(ENCODING, "");
  				tmpBlock = tmpBlock.replace(SCHEMA, "");
  			}else if(outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_NETCDF)){
  				tmpBlock = tmpBlock.replace(MIMETYPE, "APPLICATION/NETCDF");
  				tmpBlock = tmpBlock.replace(ENCODING, "");
  				tmpBlock = tmpBlock.replace(SCHEMA, "");
  			}else if(outputMimeType.equals(GenericFileDataConstants.MIME_TYPE_DGN)){
  				tmpBlock = tmpBlock.replace(MIMETYPE, "APPLICATION/DGN");
  				tmpBlock = tmpBlock.replace(ENCODING, "");
  				tmpBlock = tmpBlock.replace(SCHEMA, "");
  			}
  			
  			inputTxtWriter.write(tmpBlock);
  			
  			inputTxtWriter.flush();
  			inputTxtWriter.close();
  			
  			return true;
  			
  		} catch (IOException e) {
  			e.printStackTrace();
  			return false;
  		}
  	}
  	
  	private void executeGrassModuleStarter() {
  
  		try {
  
  			LOGGER.info("Executing GRASS module starter.");
  			
  			Runtime rt = Runtime.getRuntime();
  			
  			Process proc = rt.exec(getCommand(), getEnvp());
  			
  	        PipedOutputStream pipedOut = new PipedOutputStream();
  	        
  	        PipedInputStream pipedIn = new PipedInputStream(pipedOut);  
  			
  			// attach error stream reader
  			JavaProcessStreamReader errorStreamReader = new JavaProcessStreamReader(proc
  					.getErrorStream(), "ERROR", pipedOut);
  
  			// attach output stream reader
  			JavaProcessStreamReader outputStreamReader = new JavaProcessStreamReader(proc
  					.getInputStream(), "OUTPUT");
  			
  			// start them
  			errorStreamReader.start();
  			outputStreamReader.start();
  			
  			//fetch errors if there are any
  			BufferedReader errorReader = new BufferedReader(new InputStreamReader(pipedIn));
  			
  			String line = errorReader.readLine();
  			
  			String errors = "";		
  			
  			while(line != null){			
  				
  				errors = errors.concat(line + lineSeparator);
  				
  				line = errorReader.readLine();
  			}			
  			
  			try {
  				proc.waitFor();
  			} catch (InterruptedException e1) {
  				LOGGER.error("Java proces was interrupted.", e1);
  			}finally{
  				proc.destroy();
  			}
  
  			if(!errors.equals("")){
  				String baseDir = WebProcessingService.BASE_DIR + File.separator + "GRASS_LOGS";
  				File baseDirFile = new File(baseDir);
  				if(!baseDirFile.exists()){
  					baseDirFile.mkdir();
  				}
  				String host = WPSConfig.getInstance().getWPSConfig().getServer().getHostname();
  				if(host == null) {
  					host = InetAddress.getLocalHost().getCanonicalHostName();
  				}
  				String hostPort = WPSConfig.getInstance().getWPSConfig().getServer().getHostport();
  				File tmpLog = new File(tmpDir + fileSeparator + uuid + logFilename);
  				File serverLog = new File(baseDir + fileSeparator + uuid + logFilename);
  				
  				if(tmpLog.exists()){
  				    FileInputStream fis  = new FileInputStream(tmpLog);
  				    FileOutputStream fos = new FileOutputStream(serverLog);
  				    try {
  				        byte[] buf = new byte[1024];
  				        int i = 0;
  				        while ((i = fis.read(buf)) != -1) {
  				            fos.write(buf, 0, i);
  				        }
  				    } 
  				    catch (Exception e) {
  				        e.printStackTrace();
  				    }
  				    finally {
  				        if (fis != null) fis.close();
  				        if (fos != null) fos.close();
  				    }
  
  				}else{
  					BufferedWriter bufWrite = new BufferedWriter(new FileWriter(serverLog));
  					bufWrite.write(errors);
  					bufWrite.flush();
  					bufWrite.close();
  				}
  				LOGGER.error("An error occured while executing the GRASS GIS process.");
  				throw new RuntimeException("An error occured while executing the GRASS GIS process. See the log under " + WPSConfig.getServerBaseURL() + "/GRASS_LOGS/" + uuid + logFilename + " for more details.");
  			}
  			
  		} catch (IOException e) {
  			LOGGER.error("An error occured while executing the GRASS GIS process.", e);
  			throw new RuntimeException(e);
  		}
  	}
  	
  }
  