View Javadoc

1   package es.inteco.eni.swing;
2   
3   import java.io.File;
4   import java.io.IOException;
5   import java.util.Iterator;
6   import java.util.List;
7   import java.util.Map;
8   import java.util.Map.Entry;
9   
10  import javax.swing.JFileChooser;
11  import javax.swing.JOptionPane;
12  import javax.xml.parsers.ParserConfigurationException;
13  import javax.xml.transform.TransformerException;
14  
15  import org.apache.log4j.Logger;
16  
17  import es.inteco.eni.commons.ApplicationPropertiesManager;
18  import es.inteco.eni.commons.EniConstants;
19  import es.inteco.eni.commons.MessagesHelper;
20  import es.inteco.eni.swing.ENIValidator;
21  import es.inteco.eni.utils.ExceptionUtils;
22  import es.inteco.eni.utils.FileUtils;
23  import es.inteco.eni.xml.ENIXmlUtils;
24  import es.inteco.eni.xml.XmlNode;
25  
26  /**
27   * Clase que gestiona la apertura de ficheros
28   * 
29   * 
30   *
31   */
32  public class FileOpener {
33  	/**
34  	 * Log
35  	 */
36  	private final Logger log = Logger.getLogger(FileOpener.class);
37  
38  	/**
39  	 * Abre un fichero
40  	 * @param eniValidator Ventana del validador
41  	 * @param file Fichero
42  	 * @param tagName Nombre de la etiqueta que representa el fichero
43  	 */
44  	public void openFile(ENIValidator eniValidator, File file, String tagName){
45  		//Se muestra un mensaje al usuario indicandoles si desea abrir el fichero usando el 
46  		//Sistema Operativo o si por el contrario desea guardarlo en una determniada ruta
47  
48  		String message = MessagesHelper.getText("eni.openfile.joption.message");
49  		String title = tagName;
50  		String saveFileOption = MessagesHelper.getText("eni.openfile.joption.savefile.option");
51  		String openFileByOsOption = MessagesHelper.getText("eni.openfile.joption.openfilebyos.option");
52  		//String cancelOption = MessagesHelper.getText("eni.openfile.joption.cancel.option");
53  		String[] opts = {openFileByOsOption, saveFileOption/*, cancelOption*/};
54  		
55  		int selectedOption = JOptionPane.showOptionDialog (eniValidator, message, title, 0, 
56  				JOptionPane.QUESTION_MESSAGE, null, opts, opts[0]);
57  
58  		//Dependendiendo de lo que elija el usuario
59  		if(selectedOption==0){
60  			openFileByOs(eniValidator, file);
61  		}else if (selectedOption==1){
62  			saveFile(eniValidator, file, tagName);
63  		}
64  
65  	}
66  
67  
68  	/**
69  	 * Guarda el fichero en la ruta especificada por el usuarios
70  	 * @param eniValidator Ventana del validador
71  	 * @param file Fichero a abrir
72  	 */
73  	private void saveFile(ENIValidator eniValidator, File file, String tagName){
74  		JFileChooser fc = new JFileChooser ();
75  		//Directorio actual
76  		fc.setCurrentDirectory(eniValidator.getOpenedFilesFolder());
77  
78  		//Estable el nombre por defecto
79  		String fileExtension = FileUtils.getFileExtension(file);
80  		String fileName = tagName + (fileExtension!=null && !"".equals(fileExtension) ? "." + fileExtension : "");
81  		File toFile = new File(fileName);
82  		fc.setSelectedFile (toFile);
83  		if(fileExtension!=null && !"".equals(fileExtension)){
84  			EniFilter xmlFilter = new EniFilter(fileExtension);
85  			fc.setFileFilter (xmlFilter);
86  		}
87  
88  		//Abre el dialogo para seleccionar el fichero
89  		int result = fc.showSaveDialog(eniValidator);
90  
91  		if (result == JFileChooser.APPROVE_OPTION) {
92  			toFile = fc.getSelectedFile ();
93  			try{
94  				if (toFile.exists ()) {
95  					int response = JOptionPane.showConfirmDialog (null,
96  							MessagesHelper.getText("eni.overwrite.file.warning.message"),
97  							MessagesHelper.getText("eni.overwrite.file.warning.title"),
98  							JOptionPane.OK_CANCEL_OPTION,
99  							JOptionPane.QUESTION_MESSAGE);
100 					if (response == JOptionPane.OK_OPTION){
101 						FileUtils.copy(file, toFile);
102 					}
103 				}else{
104 					FileUtils.copy(file, toFile);
105 				}
106 			}catch (IOException e) {
107 				JOptionPane.showMessageDialog(eniValidator, 
108 						e.getMessage(),
109 						MessagesHelper.getText("eni.open.file.error.title"),
110 						JOptionPane.ERROR_MESSAGE);
111 			}
112 			eniValidator.setOpenedFilesFolder(toFile.getParentFile());
113 		} 
114 	}
115 
116 	/**
117 	 * Abre el fichero delegándolo en el Sistema operativo
118 	 * @param eniValidator Ventana del validador
119 	 * @param file Fichero a abrir
120 	 */
121 	private void openFileByOs(ENIValidator eniValidator, File file){
122 		String command = getCommand(file);
123 		ProcessThread processThread = new ProcessThread(eniValidator, command, file);
124 		processThread.start();
125 	}
126 
127 
128 	/**
129 	 * Abre un fichero representado por una cadena de texto en Base64
130 	 * @param eniValidator Ventana del validador
131 	 * @param extension Extensión del ficheor
132 	 * @param base64Str Cadena de texto en Base64 que representa el fichero
133 	 * @param tagName Nombre de la etiqueta que representa el fichero
134 	 * @throws IOException
135 	 */
136 	public void openBase64StrAsFile(ENIValidator eniValidator, String extension, String base64Str, String tagName) throws IOException{
137 		openFile(eniValidator, FileUtils.getTempFileFromBase64String(extension, base64Str), tagName);
138 	}
139 
140 
141 
142 	/**
143 	 * Abre el fichero xml
144 	 * @param eniValidator Ventana del validador
145 	 * @param formatName Nombre del fichero
146 	 * @param xmlFileContentRoot Nodo que representa el contenido del fichero
147 	 * @param tagName Nombre de la etiqueta que representa el fichero
148 	 * @throws TransformerException 
149 	 * @throws IOException 
150 	 * @throws ParserConfigurationException 
151 	 */
152 	private void openXmlAsFile(ENIValidator eniValidator, String formatName,
153 			XmlNode xmlFileContentRoot, String tagName) throws ParserConfigurationException, IOException, TransformerException {
154 		File xmlFile = ENIXmlUtils.getXmlFile(formatName, xmlFileContentRoot);
155 		openFile(eniValidator, xmlFile, tagName);
156 
157 	}
158 
159 	private void showOpenFileError(ENIValidator eniValidator){
160 		JOptionPane.showMessageDialog(eniValidator, 
161 				MessagesHelper.getText("eni.open.file.error.message"),
162 				MessagesHelper.getText("eni.open.file.error.title"),
163 				JOptionPane.ERROR_MESSAGE);
164 	}
165 
166 
167 	/**
168 	 * Abre un fichero a partir del nodo "eni:fichero" y del nodo padre
169 	 * @param eniValidator Ventana del validador
170 	 * @param xmlNode Nodo 
171 	 * @param contentFileNode Nodo "enifile:ficheroContenido"
172 	 */
173 	public void openFile(ENIValidator eniValidator, XmlNode xmlNode, XmlNode contentFileNode) {
174 		String formatName = getFormatName(contentFileNode);
175 		try{
176 			//Primera posibilidad: Fichero referenciado
177 			if(isReferenceFile(xmlNode.getlName())){
178 				String fileName = xmlNode.getValue();
179 				if(fileName.indexOf('/')==-1 && fileName.indexOf('\\')==-1){
180 					fileName = eniValidator.getParentFile().getAbsolutePath() + File.separatorChar + fileName;
181 				}
182 				openFile(eniValidator,  new File(fileName), xmlNode.getqName());
183 			}
184 			//Otra posibilidad: Fichero incluido 
185 			//Datos en formato XML
186 			else if(isXmlFile(xmlNode.getlName())){
187 				//Si es signature
188 				if(isSignatureTag(xmlNode.getlName())){
189 					//Extension (si es firma la extension es XML)
190 					openXmlAsFile(eniValidator, EniConstants.XML_EXTENSION, xmlNode, xmlNode.getqName());
191 				}else{
192 					XmlNode xmlFileContentRoot = null;
193 					if(xmlNode!=null && xmlNode.getChilds()!=null && xmlNode.getChilds().size()==1){
194 						xmlFileContentRoot = xmlNode.getChilds().entrySet().iterator().next().getValue();
195 						openXmlAsFile(eniValidator, formatName, xmlFileContentRoot, xmlNode.getqName());
196 					}
197 				}
198 			}else{
199 				//Datos en Base64
200 				String base64Str = xmlNode.getValue();//getChildValue(xmlNode, EniConstants.BINARY_VALUE_TAG);
201 				//Extension: En el caso de FirmaBase64 la extension se calculará de forma especial
202 				if(isFirmaBase64Tag(xmlNode.getlName())){
203 					formatName=getFirmaBase64ExtensionFile(xmlNode);
204 				}
205 				if(base64Str!=null){
206 					openBase64StrAsFile(eniValidator, formatName, base64Str, xmlNode.getqName());
207 				}
208 			}
209 
210 		}catch (Exception e) {
211 			log.error(ExceptionUtils.stackTraceToString(e));
212 			showOpenFileError(eniValidator);
213 		}
214 	}
215 
216 
217 	/**
218 	 * Devuelve la extension del fichero en el caso de FirmaBase64
219 	 * Para determinar la extensión se estudia el contenido del  nodo enids:TipoFirma de su bloque de firma y si tiene:
220 	 *		- El valor TF04 o TF05, asignará la extensión .csig
221 	 *		- El valor TF06, asignará la extensión .pdf
222 	 *		- El valor TF01, TF02 o TF03 no asignará extensión.
223 	 *
224 	 * @param xmlNode
225 	 * @return
226 	 */
227 	private String getFirmaBase64ExtensionFile(XmlNode xmlNode) {
228 		String extension = "";
229 		String tipoFirmaValue = getTipoFirmaValueFromFirmaBase64(xmlNode);
230 		if(EniConstants.CSIG_TIPO_FIRMA_LIST.contains(tipoFirmaValue)){
231 			extension = EniConstants.CSIG_EXTENSION;
232 		}else if(EniConstants.PDF_TIPO_FIRMA_LIST.contains(tipoFirmaValue)){
233 			extension = EniConstants.PDF_EXTENSION;
234 		}
235 		return extension;
236 	}
237 
238 	/**
239 	 * 
240 	 * Extrea el valor de la etiqueta tipoFirma a partir de la etiqueta firmaBase64
241 	 * El xml será de la forma:
242 	 * 	<enids:firma ref="">
243 	 *		<enids:TipoFirma>TF04</enids:TipoFirma>
244 	 *		<enids:ContenidoFirma>
245 	 *			<enids:FirmaConCertificado>
246 	 *				<enids:FirmaBase64>
247 	 *					.....					
248 	 *				</enids:FirmaBase64>
249 	 *			</enids:FirmaConCertificado>
250 	 *		</enids:ContenidoFirma>
251 	 *	</enids:firma>
252 	 * @param firmaBase64XmlNode nodo firmaBase64
253 	 * @return el valor de la etiqueta tipoFirma a partir de la etiqueta firmaBase64
254 	 */
255 	private String getTipoFirmaValueFromFirmaBase64(XmlNode firmaBase64XmlNode) {
256 		String firmaTag = ApplicationPropertiesManager.getProperty(EniConstants.FIRMA_TAG);
257 		XmlNode xmlNode = firmaBase64XmlNode;
258 		while(xmlNode!=null){
259 			if(firmaTag.equals(xmlNode.getlName())){
260 				return getChildValue(xmlNode, ApplicationPropertiesManager.getProperty(EniConstants.TIPO_FIRMA_TAG));
261 			}
262 			xmlNode = xmlNode.getParent();
263 		}
264 		return null;
265 	}
266 
267 
268 	private String getFormatName(XmlNode contentFileNode){
269 		return getChildValue(contentFileNode, ApplicationPropertiesManager.getProperty(EniConstants.NAME_FORMAT_TAG));
270 	}
271 
272 
273 	private String getChildValue(XmlNode xmlNode, String childTag){
274 		XmlNode child = getChild(xmlNode, childTag);
275 		return child!=null ? child.getValue() : null;
276 	}
277 
278 
279 	private XmlNode getChild(XmlNode xmlNode, String childTag){
280 		Map<String, XmlNode> childs = xmlNode.getChilds();
281 		Iterator<Entry<String, XmlNode>> it = childs.entrySet().iterator();
282 		while(it.hasNext()){
283 			Entry<String, XmlNode> entry = it.next();
284 			XmlNode child = entry.getValue();
285 			if(child.getlName().equals(childTag)){
286 				return child;
287 			}
288 		}
289 		return null;
290 	}
291 
292 
293 	private static String getCommand(File file) {
294 		//TODO Cambiar
295 		return EniConstants.EXPLORER_COMMAND;
296 	}
297 
298 
299 	/**
300 	 * Hilo para la ejecion de un proceso
301 	 * 
302 	 * 
303 	 *
304 	 */
305 	class ProcessThread extends Thread {
306 		private final Logger log = Logger.getLogger(ProcessThread.class);
307 		private static final String WINDOWS_95 = "Windows 95";
308 		private static final String WINDOWS_98 = "Windows 98";
309 		private static final String WINDOWS_ME = "Windows ME";
310 		private static final String WINDOWS = "Windows";
311 		private final String[] windows98Command = {"command.exe", "/C"};
312 		private final String[] windowsCommand = {"cmd.exe", "/C"};
313 		private final String[] linuxCommand = {"/bin/sh", "-c"};
314 
315 		/**
316 		 * Comando
317 		 */
318 		private String command;
319 		/**
320 		 * Fichero
321 		 */
322 		private File file;
323 		/**
324 		 * Ventana del validador
325 		 */
326 		private ENIValidator eniValidator;
327 
328 		/**
329 		 * Constructor
330 		 * @param command Comando
331 		 * @param file Fichero
332 		 */
333 		public ProcessThread(ENIValidator eniValidator, String command, File file){
334 			this.command = command;
335 			this.file = file;
336 			this.eniValidator = eniValidator;
337 		}
338 
339 		/**
340 		 * 
341 		 * @see java.lang.Thread#run()
342 		 */
343 		public void run() {
344 			String[] cmdarray;
345 			String os = System.getProperty("os.name");
346 			String commandToOpenFile = command + " " + "\"" + file.getAbsolutePath()+ "\"";
347 			if (os.equals(WINDOWS_95) || os.equals(WINDOWS_98) || os.equals(WINDOWS_ME)){
348 				cmdarray = new String[]{windows98Command[0], windows98Command[1], commandToOpenFile};
349 			} else if (os.startsWith(WINDOWS)){
350 				cmdarray = new String[]{windowsCommand[0], windowsCommand[1], commandToOpenFile};
351 			} else {
352 				cmdarray = new String[]{linuxCommand[0], linuxCommand[1], commandToOpenFile};
353 			}
354 
355 			//Ejecuta el comando
356 			ProcessBuilder pb = new ProcessBuilder(cmdarray);
357 			pb.redirectErrorStream(true);
358 
359 			Process process=null;
360 			try{
361 				process=pb.start();
362 				process.waitFor();
363 			}
364 			catch(IOException ioe){
365 				log.error(ExceptionUtils.stackTraceToString(ioe));
366 				showOpenFileError(eniValidator);
367 			} catch (InterruptedException e) {
368 				log.error(ExceptionUtils.stackTraceToString(e));
369 				showOpenFileError(eniValidator);
370 			}finally {
371 				if (process != null) {
372 					process.destroy();
373 				}
374 			}
375 		}
376 	}
377 
378 	/**
379 	 * Determina se le nodo es un fichero
380 	 * @param xmlNode
381 	 * @return
382 	 */
383 	public static boolean isFile(XmlNode xmlNode){
384 		return xmlNode!=null && 
385 		(isReferenceFile(xmlNode.getlName()) || 
386 				isBinaryFile(xmlNode.getlName()) || 
387 				isXmlFile(xmlNode.getlName()));
388 	}
389 
390 
391 	/**
392 	 * Determina si es un tag define un fichero como referencia
393 	 * @param lName lName
394 	 * @return Si es un tag define un fichero como referencia
395 	 */
396 	public static boolean isReferenceFile(String lName){
397 		return isFileTag(lName, EniConstants.REFFILE_KEY);
398 	}
399 
400 
401 	/**
402 	 * Determina si es un tag define un fichero en formato binario
403 	 * @param lName lName
404 	 * @return Si es un tag define un fichero en formato binario
405 	 */
406 	public static boolean isBinaryFile(String lName){
407 		return isFileTag(lName, EniConstants.BINBASEXEC_KEY);
408 	}
409 
410 
411 	/**
412 	 * Determina si es un tag define un fichero en formato XML
413 	 * @param lName lName
414 	 * @return Si es un tag define un fichero en formato XML
415 	 */
416 	public static boolean isXmlFile(String lName){
417 		return isFileTag(lName, EniConstants.XMLEXEC_KEY);
418 	}
419 
420 	private static boolean isSignatureTag(String lName){
421 		return ApplicationPropertiesManager.getProperty(EniConstants.SIGNATURE_TAG).contains(lName);
422 	}
423 
424 	private static boolean isFirmaBase64Tag(String lName){
425 		return ApplicationPropertiesManager.getProperty(EniConstants.FIRMA_BASE64_TAG).contains(lName);
426 	}
427 
428 
429 	private static boolean isFileTag(String lName, String propertyKey){
430 		boolean result = false;
431 		List<String> propertyList = ApplicationPropertiesManager.getListProperty(propertyKey);
432 		if(propertyList.contains(lName)){
433 			result = true;
434 		}
435 		return result;
436 	}
437 }