jueves, 14 de octubre de 2021

Certificados en Java (5). Renovar un certificado de la ACCV en Tomcat (NO ACABADO)

 Supongamos que tenemos instalado un certificado que va a caducar y queremos actualizarlo. Para ello podemos realizar todo el proceso desde el principio como si fuera la primera vez.

Para ello debemos

1. Crear un almacén de claves nuevo (mykeystore.jks)

keytool -keystore mykeystore -genkey -alias client -keyalg RSA


2. Importamos el certificado raiz de la ACCV que se ha descargado de su web

keytool -import -trustcacerts -alias rootaccv1 -file ACCVRAIZ1.crt -keystore mykeystore.jks


3. Ahora importamos el certificado que nos ha suministrado la ACCV

4. Y si queremos obtener un certificado "jks" a partir de un certificado p12 y que tenga contraseñas NO ASCII (ñ, acentos etc) hay que recurrir a Keystore Explorer . Esto se explica al final de otra entrada.


lunes, 11 de octubre de 2021

Certificados en Java (4). Recoger información del certificado del cliente

 Ver


https://stackoverflow.com/questions/9901248/reading-client-certificate-in-servlet


https://self-learning-java-tutorial.blogspot.com/2017/12/how-to-get-client-certificate-from.html

(este úlyimo no me funciona con vaadin)

Veamos el código en VAADIN




  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package com.vaadin.starter.skeleton;


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.vaadin.flow.component.Key;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.html.Anchor;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.PWA;
import com.vaadin.flow.server.StreamRegistration;
import com.vaadin.flow.server.StreamResource;
import com.vaadin.flow.server.VaadinRequest;
import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.server.VaadinSession;

/**
 * The main view contains a button and a click listener.
 */
@Route("")
//@PWA(name = "Project Base for Vaadin", shortName = "Project Base")
@CssImport("./styles/shared-styles.css")
@CssImport(value = "./styles/vaadin-text-field-styles.css", themeFor = "vaadin-text-field")
public class MainView extends VerticalLayout {
	private Anchor anchor;
	private TextField textField;
	X509Certificate cert=null;
	//private StreamResource resource=null;
    public MainView() {
    	cert=this.extractCertificate();
        if (cert!=null)Notification.show("Cert:"+ cert.getBasicConstraints() + "\n" +
      			 cert.getIssuerDN() + "\n" +
      			 cert.getNotAfter() + "\n" + 
      			 cert.getNotBefore() + "\n" + 
      			 cert.getSubjectDN() + "\n" );
        // Use TextField for standard text input
        boolean isValidCert=true;
        if(cert!=null) {
        	try {
        		cert.checkValidity();
        	} catch (Exception e) {
        		isValidCert=false;
        	}
        }
        if (!isValidCert) 
        	Notification.show("Certificado no válido");
        else {
        	textField = new TextField("Your name");
        
        	//IMPORTANT !!!! ficar este codi
        	anchor=new Anchor();
        	anchor.getStyle().set("display", "none");
        	anchor.setTarget("_blank");
        	//FI IMPORTANT !!!! ficar este codi
        
        	// Button click listeners can be defined as lambda expressions
        	GreetService greetService = new GreetService();
        	Button button = new Button("Say hello",
                e -> Notification.show(greetService.greet(textField.getValue())));

        
        	Button button1 = new Button("Download_I_abandona Pagina", event -> {
        		boolean isCheckPassed = true;
        		if (!isCheckPassed) {
        			Notification.show("Unfortunately you can not download this file");
        		} else {
        			final StreamResource resource = new StreamResource(textField.getValue(),
        					//() -> new ByteArrayInputStream("foo".getBytes()));
                		() -> {
                			
							try {
								return new FileInputStream("C:/Myresources/"+textField.getValue());
							} catch (FileNotFoundException e1) {
								// TODO Auto-generated catch block
								e1.printStackTrace();
							}
							return null;
						});
        			final StreamRegistration registration = VaadinSession.getCurrent().getResourceRegistry().registerResource(resource);
        			UI.getCurrent().getPage().setLocation(registration.getResourceUri());
        			if (cert!=null)System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) +"<-->"+textField.getValue()+" -------> "+ cert.getSubjectDN());
        		}
        	});
        
        	Button button2 = new Button("download_BO", event -> forceDownload());
        	// Theme variants give you predefined extra styles for components.
        	// Example: Primary button is more prominent look.
        	button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);

        	// You can specify keyboard shortcuts for buttons.
        	// Example: Pressing enter in this view clicks the Button.
        	button.addClickShortcut(Key.ENTER);

        	// Use custom CSS classes to apply styling. This is defined in shared-styles.css.
        	addClassName("centered-content");

        	add(textField, button, button1, button2, anchor);
        
        }	
    }
    
    /* Este es el BO !!!!!*/
    protected void forceDownload() {
    	StreamResource resource= new StreamResource(textField.getValue(),
                () -> {
        			try {
						return new FileInputStream("C:/MyResources/"+textField.getValue( ) );
					} catch (FileNotFoundException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					return null;
				});
    	this.anchor.setHref(resource); // downloadWidget is an Anchor
    	//
    	//UI.getCurrent().getPage().executeJavaScript("$0.click();", this.downloadWidget.getElement());
    	UI.getCurrent().getPage().executeJs("$0.click();", anchor.getElement());
    	if (cert!=null)System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) +"<-->"+textField.getValue()+" -------> "+ cert.getSubjectDN());
    }
    
    //protected X509Certificate extractCertificate(HttpServletRequest req) {
    protected X509Certificate extractCertificate() {
    	VaadinRequest req= VaadinService.getCurrentRequest();
    	X509Certificate[] certs = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
        if (null != certs && certs.length > 0) {
        	System.out.println("Cert:"+ certs[0].getBasicConstraints() + "\n" +
        			 certs[0].getIssuerDN() + "\n" +
        			 certs[0].getNotAfter() + "\n" + 
        			 certs[0].getNotBefore() + "\n" + 
        			 certs[0].getSubjectDN() + "\n" );
        	Notification.show("Cert:"+ certs[0].getBasicConstraints() + "\n" +
       			 certs[0].getIssuerDN() + "\n" +
       			 certs[0].getNotAfter() + "\n" + 
       			 certs[0].getNotBefore() + "\n" + 
       			 certs[0].getSubjectDN() + "\n" );
            return certs[0];
        }
        //throw new RuntimeException("No X.509 client certificate found in request");
        return null;
    }
}


martes, 5 de octubre de 2021

PDF con PDFBox (6) Translaciones, rotaciones, escalado y no perderse en el intento. Ejemplo práctico para generar copia auténtica d eun documento

 0. Introducción

Parece ser que los que han desarrollado el modelo PDF y por ende los de PDFBos, son unos talentos en álgebra, pero, salvando las diferencias con ellos se puede llegar a cierto nivel,  si se tiene en cuenta las nociones básicas que vemos a continuación.


1. Operaciones básicas

1. Para empezar debemos crear un nuevo documento PDF o cargar uno existente, y escoger una página (en principio la primera)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
//=====================================
//       DOCUMENTO EXISTENTE
//=====================================

//1.1 Cargar un documento existente
PDDocument document = PDDocument.load(new File(filePath));

//1.2Seleccionar la primera página
PDPage page = document.getDocumentCatalog().getPages().get(0);


//=====================================
//       DOCUMENTO NUEVO
//=====================================

//2.Crear un nuevo documento 
PDDocument doc = new PDDocument();

//2.1 Crear una nueva página y añadirla al documento
PDPage page1 = new PDPage();
doc.addPage(page1);

2. Crear un marco (rectángulo), SIN AFECTAR AL GROSOR DE LOS MARCOS EXISTENTES. Esta acción debe de ser la primera que se haga, pues puede afectar seriamente al grosor de los marcos existentes. Para ello se utiliza la opción "PDPageContentStream.AppendMode.APPEND". Ojo hay que tener en cuenta que solo debemos hacer APPEND una vez y al principio, pues resetea los cambios hechos hasta ahora. 

Para ello creamos un PDPageContentStream para ir añadiendo el marco

1
2
3
4
5
6
7
// Hay que abrir siempre un PDPageContentStream sobre la página y documento
PDPageContentStream cs = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, false, false);
cs.addRect(0, 0, width, height); // Rectangul (marco)
cs.setLineWidth(0.1f); (grosor de línea)
cs.setStrokingColor(Color.RED); (Color de la línea)
cs.stroke(); 
cs.close();

3. Posicionarse en la hoja para escribir texto: Para escribir texto se utiliza el método showText("texto a mostrar")  aplicado al PDPageContentStream. El proceso és el siguiente tal como se muestra en el código:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Hay que abrir siempre un PDPageContentStream sobre la página y documento
cs = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.PREPEND, false, false);
// Abrimos el procweso de escritura de texto
cs.beginText(); 
//Opcionalmente definimos una matriz de transformación
//  En este caso Rotación de 90 sobre loas coordenadas (0,0) en sentido de las agujas del reloj
Matrix matrix = Matrix.getRotateInstance(Math.toRadians(90), 0, 0);
//Aplicamos la transformación
cs.setTextMatrix(matrix);
//Definimos el ipo de lera (fuente)
cs.setFont(PDType1Font.HELVETICA,13);
//Nos deslazamos relativamente del punto inicial 
// En este caso, al hacer un giro de 90 la hoja queda apaisada, por ta
cs.newLineAtOffset(530, 6); 
//Escribimos "texto 1"
cs.showText("texto 1"); 
//Sobre la misma línea y a continuación escribimos "texto2"
// y no hemos hecho ningún desplazamiento
cs.showText("texto 2"); 
//Nos situamos 10 puntos más abajo pero respecto de la translación anterior 
//  (sin verse afectadas las coordenadas por el texto escrito)
cs.newLineAtOffset(0, 10);  
// Y imprimimos "texto 3" justo debajo de donde se ha impreeso "texto 1"
cs.showText("texto 1"); 
//Cuando terminamos de imprimir todo el texto debemos indicar el "endText()"
cc.endText();
//Cerramos el stream
cs.close();

4.  Si nos perdemos (no sabemos donde andamos, o sea no sabemos cual es la posición del cursor actual). Cerramos el PDPageContentStream y lo volvemos a brir. Si no funciona cambiamos la matrix de giro  del código anterior  por esta que no hace nada y deja la posición al (0,0)

1
2
3
4
5
//Opcionalmente definimos una matriz de transformación
//  En este caso Rotación de 0 sobre loas coordenadas (0,0) en sentido de las agujas del reloj
Matrix matrix = Matrix.getRotateInstance(Math.toRadians(0), 0, 0);
//Aplicamos la transformación
cs.setTextMatrix(matrix);

5. Vamos a aplicar una translación y posteriormente un escalado reductor.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/ Factor de escalado de toda la página
float factor=0.75f; 
PDPageContentStream cs = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.PREPEND, false, false);
//Matriz de escalado reductor de 0.75 en ambos ejes (para no distorsionar)
Matrix matrix = Matrix.getScaleInstance(factor,factor);
//Aplicamos la transformación
cs.transform(matrix);
cs.close();
        
// Translación de 25 en eje x y 50 en eje y a toda la página
float tx=25f;
floatty=50f;
PDPageContentStream cs = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.PREPEND, false, false);
// Matriz de translación
Matrix matrix = Matrix.getTranslateInstance(tx, ty);
cs.transform(matrix);
cs.close();

2. Ejemplo

En este ejemplo se muestra como se hace un documento como este:



donde se ha  comprimido el documentoto y desplazado a la derecha para mostrar información del CSV, y firmas etc en los bordes.

Aquí está el código. Hay que tener en cuenta que faltan los programs de utilidad de descargar información de la BD y de Alfresco.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.util.Matrix;

import gexflowcsv.GexflowCSV;
import openadmin.utils.other.BarCodeUtils;
import openadmin.dao.base.DaoOperationFacadeEdu;
import openadmin.dao.implem.DaoJpaEdu;
import openadmin.model.control.User;
import openadmin.utils.basic.ExecutionTypeEnum;
import openadmin.utils.basic.PropertyUtilsEdu;
import openadmin.utils.basic.StringUtilsEdu;
import openadmin.utils.graphic.GraphicUtils;

public class ActionKK {

	public static float mm2point = 2.834f;

	/**
	 * Get the document and modify it for having a "Copia Auténtica"
	 * 
	 * call: ImprimirDocPorCSV(daoGexflow, AlbaProps, CMISProps,
	 * CSV,"/home/eduard/Myresources", 19f,8f,22f) ;
	 * 
	 * @param props
	 * @param CSV
	 * @param filePath
	 * @param LMarginMm
	 * @param RMarginMm
	 * @param TMarginMm
	 * @throws Exception
	 */
	public static void ImprimirDocPorCSV(DaoOperationFacadeEdu DAOGexflow, Properties AlbaProps, Properties CMISProps,
			String CSV, String folderPath, float LMarginMm, float RMarginMm, float TMarginMm) throws Exception {

		// 0. Parameters
		float A4WMm = 210f; // A4 width in mm.

		float scaleX = 0.4f; // For Barcode
		float scaleY = 0.45f; // For Barcode

		float factor = (A4WMm - LMarginMm - RMarginMm) / A4WMm; // Scale of document into the frame

		String sedeURL = AlbaProps.getProperty("gexflow.csv.url");

		// 1. Get info of the document
		List<Object[]> lDoc = GexflowCSV.getDocBycsv(DAOGexflow, CSV);
		// PDDocument document = PDDocument.load(new File(filePath));

		// 2. Load the document form alfresco
		PDDocument document = PDDocument
				.load(GexflowCSV.getCMISContentStream(CMISProps, GexflowCSV.getPdfUuid(lDoc), "id"));
		
		// If has signatures then put the csv and modify document with signatures 
		if (GexflowCSV.hasFirmantes(lDoc)) {
			int nPage = 1;
			int nPages = document.getDocumentCatalog().getPages().getCount();

			// 3. Apply changes for every page
			// PDPage page = document.getDocumentCatalog().getPages().get(0);

			for (PDPage page : document.getDocumentCatalog().getPages()) {

				// 4. Get dimensions of crop box
				PDRectangle mediaBox = page.getMediaBox();
				float width = mediaBox.getWidth();
				float height = mediaBox.getHeight();
				// System.out.println("width="+width + " height="+height);
				if ((width - 595.30396f) > 1)
					throw new Exception("Invalid paper size");

				// 5. Draw a black rectangle APPEND-> For the first time!!!)
				PDPageContentStream cs = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND,
						false, false);
				cs.addRect(0, height, width, -height); // APPEND
				cs.setLineWidth(0.1f * mm2point);
				cs.setStrokingColor(Color.RED);
				cs.stroke();
				// cs.close();

				// 6. Add the CSV barcode
				float heighToRest = 390;
				// BarCode Code128
				BufferedImage bcImage = BarCodeUtils.writeBarcodeCode128Zxing2File(CSV, 1000, 80, null);
				// Rotate image
				bcImage = GraphicUtils.rotate(bcImage, -90);
				// Convert image to PDF object
				PDImageXObject pdImage = LosslessFactory.createFromImage(document, bcImage);
				cs.drawImage(pdImage, -50, height - heighToRest, pdImage.getWidth() * scaleX,
						pdImage.getHeight() * scaleY);

				// 6.1. Remove borders of bar code using white rectangle
				cs.addRect(-50, height - heighToRest, pdImage.getWidth() * scaleX, pdImage.getHeight() * scaleY); // APPEND
				cs.setLineWidth(1f * mm2point);
				cs.setStrokingColor(Color.WHITE);
				cs.stroke();
				cs.close();

				// 7. Rotate the page and print CSV text (From now on , use PREPEND and NOT
				// APPEND)
				cs = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.PREPEND, false, false);
				cs.beginText();
				Matrix matrixkk = Matrix.getRotateInstance(Math.toRadians(90), 0, 0);
				cs.setTextMatrix(matrixkk);
				cs.setFont(PDType1Font.HELVETICA, 13);
				cs.newLineAtOffset(530, 6); //
				cs.showText(CSV);

				// 8. Print "Copia auténtica..."
				String rollet0 = "Copia auténtica. ";
				String rollet1 = "Mediante el código impreso puede combrobar la validez de la firma";
				String rollet2 = " electrónica en la URL:  ";

				cs.setNonStrokingColor(Color.DARK_GRAY);
				cs.setFont(PDType1Font.HELVETICA_BOLD_OBLIQUE, 10);
				cs.newLineAtOffset(-515, 30); //
				cs.showText(rollet0);
				cs.setFont(PDType1Font.HELVETICA_OBLIQUE, 10);
				cs.showText(rollet1);

				cs.newLineAtOffset(0, -15); //
				cs.showText(rollet2);

				cs.setFont(PDType1Font.HELVETICA_BOLD_OBLIQUE, 11);
				cs.showText(sedeURL);
				cs.endText();

				// 9. Print "Fecha de impresion..."
				// 9.1 undo the rotation
				matrixkk = Matrix.getRotateInstance(Math.toRadians(0), 0, 0);
				cs.setFont(PDType1Font.HELVETICA_BOLD_OBLIQUE, 10);
				cs.beginText();
				cs.setTextMatrix(matrixkk);
				String fechita1 = "Fecha de impresión: ";
				// String fechita2="Martes, 4 de Octubre de 2021 7:38";
				String fechita2 = GexflowCSV.getInfoImpresion();
				String paginitas = "Página " + nPage++ + " de " + nPages;
				cs.newLineAtOffset(5, -15); //
				cs.showText(fechita1);
				cs.setFont(PDType1Font.HELVETICA_OBLIQUE, 10);
				cs.showText(fechita2);

				cs.newLineAtOffset(500, 0); //
				cs.showText(paginitas);

				cs.endText();
				// end undo rotation
				cs.close();

				// 10. Scale the page
				cs = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.PREPEND, false, false);
				Matrix matrix = Matrix.getScaleInstance(factor, factor);
				cs.transform(matrix);
				cs.close();

				// 11. Trasllate the page
				float trX = LMarginMm * mm2point;
				float trY = (1 - factor) * height - TMarginMm * mm2point;
				// System.out.println("trX="+trX + " trY="+trY);
				cs = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.PREPEND, false, false);
				Matrix matrix1 = Matrix.getTranslateInstance(trX, trY);
				cs.transform(matrix1);
				cs.close();

				// 11. Write DECRETO and signatures
				cs = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.PREPEND, false, false);
				cs.setFont(PDType1Font.HELVETICA_BOLD, 9);
				cs.beginText();

				// 11.1. Decreto / acta
				cs.newLineAtOffset(trX + 2 * mm2point, height - 5 * mm2point);
				String sDecret = GexflowCSV.getInfoDecret(lDoc);
				// If it is not Decreto or Acta then doen't print this line
				if (sDecret.trim().length() > 5) {
					cs.showText(GexflowCSV.getInfoDecret(lDoc)); // Decret nº 2021 -2

					// 11.2. FIRMADO
					cs.newLineAtOffset(0, -11);
				}
				cs.showText("FIRMADO");

				// 11.3 Firmantes
				cs.setFont(PDType1Font.HELVETICA, 7);
				for (String firmantes : GexflowCSV.getInfoFirmantes(lDoc)) {
					cs.newLineAtOffset(0, -7);
					cs.showText(firmantes);
				}
				cs.endText();
				cs.close(); // don't forget that one!

			}
		}
		String myFileName = folderPath + "/"
				+ GexflowCSV.getPdfFileName(lDoc).replace(".pdf", ".esc" + ((int) (100 * factor)) + ".pdf");
		System.out.println(myFileName);
		File myFile = new File(myFileName);
		// myFile.createNewFile();
		document.save(myFile);
		document.close();
	}

	
	public static void main(String[] args) {
		try {
	
			Properties AlbaProps = PropertyUtilsEdu.getProperties(ExecutionTypeEnum.NO_JAR, "alba");
			Properties CMISProps = PropertyUtilsEdu.getProperties(ExecutionTypeEnum.NO_JAR, "cmis");

			Properties DAOProps = PropertyUtilsEdu.getProperties(ExecutionTypeEnum.NO_JAR, "dao");
			String[] daos = StringUtilsEdu.splitAndTrim(DAOProps.getProperty("persistence.units"), ";");
			String[] daoHosts = StringUtilsEdu.splitAndTrim(DAOProps.getProperty("persistence.hosts"), ";");
			String[] daosActives = StringUtilsEdu.splitAndTrim(DAOProps.getProperty("persistence.units.active"), ";");
			User myUser = new User();
			myUser.setDescription("Liuardo");
			short i = 1;
			DaoOperationFacadeEdu daoGexflow = new DaoJpaEdu(myUser, daos[i], daoHosts[i], i, null,
					Boolean.parseBoolean(daosActives[i]), "1.1.1.1", "Liuardo", "Chrome", "11111");

			String myFolder = "/home/eduard/MyResources";
			String CSV = "e-Aqhe5yWHNm5PK*Yt+8iIlTJ*fHwEXX71miw7w"; // Acta
			ImprimirDocPorCSV(daoGexflow, AlbaProps, CMISProps, CSV, myFolder, 19f, 8f, 22f);

			CSV = "XZW9VdYdgm3v3e-9uMZxF2mHIrzK+GcKqMb3MsQ"; // Decret
			ImprimirDocPorCSV(daoGexflow, AlbaProps, CMISProps, CSV, myFolder, 19f, 8f, 22f);

			CSV = "JveQte+exrJZ09xMw76*vzbvLYvCJLPT0iwFpOw"; // 6 firmes !!
			ImprimirDocPorCSV(daoGexflow, AlbaProps, CMISProps, CSV, myFolder, 19f, 8f, 22f);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}