1 /* 2 * db2sa: DB2 Syntax Assistant 3 * Copyright (C) Andres Gomez Casanova 4 * 5 * This file is part of db2sa. 6 * 7 * db2sa is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU Lesser General Public License as published by 9 * the Free Software Foundation; either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * db2sa is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public License 18 * along with this library; if not, see <http://www.gnu.org/licenses/>. 19 * 20 * Contact: 21 * a n g o c a at y a h o o dot c o m 22 * Cra. 45 No 61 - 31, Bogota, Colombia. 23 * 24 * Author: $LastChangedBy: angoca $: 25 * Date: $LastChangedDate: 2009-07-08 19:56:43 +0200 (Wed, 08 Jul 2009) $: 26 * Revision: $LastChangedRevision: 357 $: 27 * URL: $HeadURL: https://db2sa.svn.sourceforge.net/svnroot/db2sa/branches/db2sa_beta/source-code/src/main/java/name/angoca/db2sa/core/executer/Executer.java $: 28 */ 29 package name.angoca.db2sa.core.executer; 30 31 import java.io.BufferedReader; 32 import java.io.IOException; 33 import java.io.InputStreamReader; 34 import java.io.Reader; 35 import java.util.StringTokenizer; 36 37 import name.angoca.db2sa.Configurator; 38 import name.angoca.db2sa.Constants; 39 import name.angoca.db2sa.ExecutionState; 40 import name.angoca.db2sa.cli.OutputWriter; 41 import name.angoca.db2sa.cli.exceptions.OutputWriterException; 42 import name.angoca.db2sa.messages.Messages; 43 44 import org.slf4j.Logger; 45 import org.slf4j.LoggerFactory; 46 47 /** 48 * This is the implementation of the executer. TODO validar que la ejecución de 49 * DB2 se puede hacer desde una misma clase en varias plataformas, o si es 50 * necesario validar esto. <br/> 51 * <b>Control Version</b><br /> 52 * <ul> 53 * <li>0.0.1 Class creation.</li> 54 * <li>0.1.0 Singleton pattern, analyze of exit token.</li> 55 * <li>0.1.1 Use of streams.</li> 56 * <li>0.1.2 Execution state.</li> 57 * <li>0.1.3 Enum.</li> 58 * <li>0.1.4 Close de streams and get instance synchronized.</li> 59 * <li>0.1.5 Name of a state.</li> 60 * <li>0.1.6 final.</li> 61 * <li>1.0.0 Moved to version 1.</li> 62 * </ul> 63 * 64 * @author Andres Gomez Casanova <a 65 * href="mailto:a n g o c a at y a h o o dot c o m">(AngocA)</a> 66 * @version 1.0.0 2009-07-19 67 */ 68 public final class Executer { 69 /** 70 * Logger. 71 */ 72 private static final Logger LOGGER = LoggerFactory 73 .getLogger(Executer.class); 74 75 /** 76 * Singleton pattern. 77 */ 78 private static Executer s_instance; 79 80 /** 81 * Set of tokens to exit the execution. 82 */ 83 private final String m_tokens; 84 85 /** 86 * Private default constructor. 87 */ 88 private Executer() { 89 this.m_tokens = Configurator.getInstance().getProperty(Constants.EXIT); 90 if (this.m_tokens == null) { 91 // TODO Lanzar una excepción propia 92 throw new RuntimeException(Messages 93 .getString("JlineInterfaceController" //$NON-NLS-1$ 94 + ".NoExitTokensDefined")); //$NON-NLS-1$ 95 } 96 } 97 98 /** 99 * Implementation of Singleton pattern, returns the sole instance. 100 * 101 * @return The sole instance of the executer. 102 */ 103 public static Executer getInstance() { 104 synchronized (Executer.LOGGER) { 105 if (Executer.s_instance == null) { 106 Executer.s_instance = new Executer(); 107 } 108 } 109 return Executer.s_instance; 110 } 111 112 /** 113 * Executes the given command and returns a code that means the execution 114 * state. 115 * 116 * @param command 117 * Command to execute. 118 * @param writer 119 * The output's writer. 120 * @return A signal that indicates the state of the command. 121 * @throws OutputWriterException 122 * If there is a problem when writing. 123 */ 124 public ExecutionState/* ! */execute(final String/* ! */command, 125 final OutputWriter/* ! */writer) throws OutputWriterException { 126 // No body uses the unknown state, it just for initialize the variable. 127 ExecutionState state = ExecutionState.UNKNOWN; 128 129 BufferedReader bfStream = null; 130 Reader reader = null; 131 132 try { 133 // TODO la salida estandar y de error cómo se van a manejar? 134 // TODO Cuando el comando no empieza con la palabra DB2 y no es 135 // ninguno de los otros comandos, adicionar este palabra y 136 // ejecutarlo sobre DB2 137 Executer.LOGGER.info("Execute: {}", command); //$NON-NLS-1$ 138 139 if (this.isAnExitToken(command)) { 140 state = ExecutionState.APPLICATION_EXIT; 141 } else { 142 state = ExecutionState.EXECUTED; 143 if (command.compareTo("") != 0) { //$NON-NLS-1$ 144 // TODO Analizar los comandos que no comienzan con la parte 145 // de db2. 146 // TODO usar el output printer para no tener que concatenar 147 // la salida 148 // TODO usar un input stream para poder modificar el comando 149 // ejecutado (como cuando se pide la contrasegna) 150 // TODO finalizar o cerrar todos los objetos despues de 151 // usados 152 final Process proc = Runtime.getRuntime().exec(command); 153 reader = new InputStreamReader(proc.getInputStream()); 154 bfStream = new BufferedReader(reader); 155 String current = ""; //$NON-NLS-1$ 156 while (current != null) { 157 current = bfStream.readLine(); 158 if (current != null) { 159 writer.writeLine(current); 160 } 161 } 162 } 163 } 164 } catch (IOException e) { 165 // TODO Auto-generated catch block 166 e.printStackTrace(); 167 } finally { 168 169 try { 170 if (bfStream != null) { 171 bfStream.close(); 172 } 173 } catch (IOException e) { 174 // TODO Auto-generated catch block 175 e.printStackTrace(); 176 } 177 178 try { 179 if (reader != null) { 180 reader.close(); 181 } 182 } catch (IOException e) { 183 // TODO Auto-generated catch block 184 e.printStackTrace(); 185 } 186 } 187 Executer.LOGGER.debug("{} -> {}", command, state); //$NON-NLS-1$ 188 return state; 189 } 190 191 /** 192 * @param command 193 * @return 194 */ 195 /** 196 * Analyze the current command to see if the application has to finish. 197 * 198 * @param command 199 * Command entered. 200 * @return true if the application has to finish. 201 */ 202 private boolean isAnExitToken(final String/* ! */command) { 203 boolean exit = false; 204 final StringTokenizer tokens = new StringTokenizer(this.m_tokens); 205 while (tokens.hasMoreElements()) { 206 // FIXME cuando se hace ctrl + D hay una excepcion aqui. 207 if (command.compareToIgnoreCase(tokens.nextToken()) == 0) { 208 exit = true; 209 } 210 } 211 return exit; 212 } 213 }